]> rtime.felk.cvut.cz Git - pes-rpp/rpp-lwip.git/blob - test/unit/tcp/tcp_helper.c
Fixed tcp unit tests after introducing ip_addr_p_t and letting tcp_input check for...
[pes-rpp/rpp-lwip.git] / test / unit / tcp / tcp_helper.c
1 #include "tcp_helper.h"
2
3 #include "lwip/tcp_impl.h"
4 #include "lwip/stats.h"
5 #include "lwip/pbuf.h"
6 #include "lwip/inet_chksum.h"
7
8 #if !LWIP_STATS || !TCP_STATS || !MEMP_STATS
9 #error "This tests needs TCP- and MEMP-statistics enabled"
10 #endif
11
12 /** Remove all pcbs on the given list. */
13 static void
14 tcp_remove(struct tcp_pcb* pcb_list)
15 {
16   struct tcp_pcb *pcb = pcb_list;
17   struct tcp_pcb *pcb2;
18
19   while(pcb != NULL) {
20     pcb2 = pcb;
21     pcb = pcb->next;
22     tcp_abort(pcb2);
23   }
24 }
25
26 /** Remove all pcbs on listen-, active- and time-wait-list (bound- isn't exported). */
27 void
28 tcp_remove_all(void)
29 {
30   tcp_remove(tcp_listen_pcbs.pcbs);
31   tcp_remove(tcp_active_pcbs);
32   tcp_remove(tcp_tw_pcbs);
33   fail_unless(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
34   fail_unless(lwip_stats.memp[MEMP_TCP_PCB_LISTEN].used == 0);
35   fail_unless(lwip_stats.memp[MEMP_TCP_SEG].used == 0);
36   fail_unless(lwip_stats.memp[MEMP_PBUF_POOL].used == 0);
37 }
38
39 /** Create a TCP segment usable for passing to tcp_input
40  * - IP-addresses, ports, seqno and ackno are taken from pcb
41  * - seqno and ackno can be altered with an offset
42  */
43 struct pbuf*
44 tcp_create_rx_segment(struct tcp_pcb* pcb, void* data, size_t data_len, u32_t seqno_offset,
45                       u32_t ackno_offset, u8_t headerflags)
46 {
47   return tcp_create_segment(&pcb->remote_ip, &pcb->local_ip, pcb->remote_port, pcb->local_port,
48     data, data_len, pcb->rcv_nxt + seqno_offset, pcb->snd_nxt + ackno_offset, headerflags);
49 }
50
51 /** Create a TCP segment usable for passing to tcp_input */
52 struct pbuf*
53 tcp_create_segment(ip_addr_t* src_ip, ip_addr_t* dst_ip,
54                    u16_t src_port, u16_t dst_port, void* data, size_t data_len,
55                    u32_t seqno, u32_t ackno, u8_t headerflags)
56 {
57   struct pbuf* p;
58   struct ip_hdr* iphdr;
59   struct tcp_hdr* tcphdr;
60   u16_t pbuf_len = (u16_t)(sizeof(struct ip_hdr) + sizeof(struct tcp_hdr) + data_len);
61
62   p = pbuf_alloc(PBUF_RAW, pbuf_len, PBUF_POOL);
63   EXPECT_RETNULL(p != NULL);
64   EXPECT_RETNULL(p->next == NULL);
65
66   memset(p->payload, 0, p->len);
67
68   iphdr = p->payload;
69   /* fill IP header */
70   iphdr->dest.addr = dst_ip->addr;
71   iphdr->src.addr = src_ip->addr;
72   IPH_VHLTOS_SET(iphdr, 4, IP_HLEN / 4, 0);
73   IPH_LEN_SET(iphdr, htons(p->tot_len));
74   IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
75
76   pbuf_header(p, -(s16_t)sizeof(struct ip_hdr));
77
78   tcphdr = p->payload;
79   tcphdr->src   = htons(src_port);
80   tcphdr->dest  = htons(dst_port);
81   tcphdr->seqno = htonl(seqno);
82   tcphdr->ackno = htonl(ackno);
83   TCPH_HDRLEN_SET(tcphdr, sizeof(struct tcp_hdr)/4);
84   TCPH_FLAGS_SET(tcphdr, headerflags);
85   tcphdr->wnd   = htons(TCP_WND);
86
87   /* copy data */
88   memcpy((char*)tcphdr + sizeof(struct tcp_hdr), data, data_len);
89
90   /* calculate checksum */
91
92   tcphdr->chksum = inet_chksum_pseudo(p, src_ip, dst_ip,
93           IP_PROTO_TCP, p->tot_len);
94
95   pbuf_header(p, sizeof(struct ip_hdr));
96
97   return p;
98 }
99
100 /** Safely bring a tcp_pcb into the requested state */
101 void
102 tcp_set_state(struct tcp_pcb* pcb, enum tcp_state state, ip_addr_t* local_ip,
103                    ip_addr_t* remote_ip, u16_t local_port, u16_t remote_port)
104 {
105   /* @todo: are these all states? */
106   /* @todo: remove from previous list */
107   pcb->state = state;
108   if (state == ESTABLISHED) {
109     TCP_REG(&tcp_active_pcbs, pcb);
110     pcb->local_ip.addr = local_ip->addr;
111     pcb->local_port = local_port;
112     pcb->remote_ip.addr = remote_ip->addr;
113     pcb->remote_port = remote_port;
114   } else if(state == LISTEN) {
115     TCP_REG(&tcp_listen_pcbs.pcbs, pcb);
116     pcb->local_ip.addr = local_ip->addr;
117     pcb->local_port = local_port;
118   } else if(state == TIME_WAIT) {
119     TCP_REG(&tcp_tw_pcbs, pcb);
120     pcb->local_ip.addr = local_ip->addr;
121     pcb->local_port = local_port;
122     pcb->remote_ip.addr = remote_ip->addr;
123     pcb->remote_port = remote_port;
124   } else {
125     fail();
126   }
127 }
128
129 void
130 test_tcp_counters_err(void* arg, err_t err)
131 {
132   struct test_tcp_counters* counters = arg;
133   EXPECT_RET(arg != NULL);
134   counters->err_calls++;
135   counters->last_err = err;
136 }
137
138 static void
139 test_tcp_counters_check_rxdata(struct test_tcp_counters* counters, struct pbuf* p)
140 {
141   struct pbuf* q;
142   u32_t i, received;
143   if(counters->expected_data == NULL) {
144     /* no data to compare */
145     return;
146   }
147   EXPECT_RET(counters->recved_bytes + p->tot_len <= counters->expected_data_len);
148   received = counters->recved_bytes;
149   for(q = p; q != NULL; q = q->next) {
150     char *data = q->payload;
151     for(i = 0; i < q->len; i++) {
152       EXPECT_RET(data[i] == counters->expected_data[received]);
153       received++;
154     }
155   }
156   EXPECT(received == counters->recved_bytes + p->tot_len);
157 }
158
159 err_t
160 test_tcp_counters_recv(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t err)
161 {
162   struct test_tcp_counters* counters = arg;
163   EXPECT_RETX(arg != NULL, ERR_OK);
164   EXPECT_RETX(pcb != NULL, ERR_OK);
165   EXPECT_RETX(err == ERR_OK, ERR_OK);
166
167   if (p != NULL) {
168     if (counters->close_calls == 0) {
169       counters->recv_calls++;
170       test_tcp_counters_check_rxdata(counters, p);
171       counters->recved_bytes += p->tot_len;
172     } else {
173       counters->recv_calls_after_close++;
174       counters->recved_bytes_after_close += p->tot_len;
175     }
176     pbuf_free(p);
177   } else {
178     counters->close_calls++;
179   }
180   EXPECT(counters->recv_calls_after_close == 0 && counters->recved_bytes_after_close == 0);
181   return ERR_OK;
182 }
183
184 /** Allocate a pcb and set up the test_tcp_counters_* callbacks */
185 struct tcp_pcb*
186 test_tcp_new_counters_pcb(struct test_tcp_counters* counters)
187 {
188   struct tcp_pcb* pcb = tcp_new();
189   if (pcb != NULL) {
190     /* set up args and callbacks */
191     tcp_arg(pcb, counters);
192     tcp_recv(pcb, test_tcp_counters_recv);
193     tcp_err(pcb, test_tcp_counters_err);
194   }
195   return pcb;
196 }
197
198 /** Calls tcp_input() after adjusting current_iphdr_dest */
199 void test_tcp_input(struct pbuf *p, struct netif *inp)
200 {
201   struct ip_hdr *iphdr = (struct ip_hdr*)p->payload;
202   ip_addr_copy(current_iphdr_dest, iphdr->dest);
203   ip_addr_copy(current_iphdr_src, iphdr->src);
204   current_netif = inp;
205   current_header = iphdr;
206
207   tcp_input(p, inp);
208
209   current_iphdr_dest.addr = 0;
210   current_iphdr_src.addr = 0;
211   current_netif = NULL;
212   current_header = NULL;
213 }