ReactOS  0.4.14-dev-358-gbef841c
tcp_helper.c
Go to the documentation of this file.
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 
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 
27 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 
40 static struct pbuf*
42  u16_t src_port, u16_t dst_port, void* data, size_t data_len,
43  u32_t seqno, u32_t ackno, u8_t headerflags, u16_t wnd)
44 {
45  struct pbuf *p, *q;
46  struct ip_hdr* iphdr;
47  struct tcp_hdr* tcphdr;
48  u16_t pbuf_len = (u16_t)(sizeof(struct ip_hdr) + sizeof(struct tcp_hdr) + data_len);
49 
50  p = pbuf_alloc(PBUF_RAW, pbuf_len, PBUF_POOL);
51  EXPECT_RETNULL(p != NULL);
52  /* first pbuf must be big enough to hold the headers */
53  EXPECT_RETNULL(p->len >= (sizeof(struct ip_hdr) + sizeof(struct tcp_hdr)));
54  if (data_len > 0) {
55  /* first pbuf must be big enough to hold at least 1 data byte, too */
56  EXPECT_RETNULL(p->len > (sizeof(struct ip_hdr) + sizeof(struct tcp_hdr)));
57  }
58 
59  for(q = p; q != NULL; q = q->next) {
60  memset(q->payload, 0, q->len);
61  }
62 
63  iphdr = p->payload;
64  /* fill IP header */
65  iphdr->dest.addr = dst_ip->addr;
66  iphdr->src.addr = src_ip->addr;
67  IPH_VHL_SET(iphdr, 4, IP_HLEN / 4);
68  IPH_TOS_SET(iphdr, 0);
69  IPH_LEN_SET(iphdr, htons(p->tot_len));
70  IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
71 
72  /* let p point to TCP header */
73  pbuf_header(p, -(s16_t)sizeof(struct ip_hdr));
74 
75  tcphdr = p->payload;
76  tcphdr->src = htons(src_port);
77  tcphdr->dest = htons(dst_port);
78  tcphdr->seqno = htonl(seqno);
79  tcphdr->ackno = htonl(ackno);
80  TCPH_HDRLEN_SET(tcphdr, sizeof(struct tcp_hdr)/4);
81  TCPH_FLAGS_SET(tcphdr, headerflags);
82  tcphdr->wnd = htons(wnd);
83 
84  if (data_len > 0) {
85  /* let p point to TCP data */
86  pbuf_header(p, -(s16_t)sizeof(struct tcp_hdr));
87  /* copy data */
88  pbuf_take(p, data, data_len);
89  /* let p point to TCP header again */
90  pbuf_header(p, sizeof(struct tcp_hdr));
91  }
92 
93  /* calculate checksum */
94 
95  tcphdr->chksum = inet_chksum_pseudo(p,
96  IP_PROTO_TCP, p->tot_len, src_ip, dst_ip);
97 
98  pbuf_header(p, sizeof(struct ip_hdr));
99 
100  return p;
101 }
102 
104 struct pbuf*
106  u16_t src_port, u16_t dst_port, void* data, size_t data_len,
107  u32_t seqno, u32_t ackno, u8_t headerflags)
108 {
109  return tcp_create_segment_wnd(src_ip, dst_ip, src_port, dst_port, data,
110  data_len, seqno, ackno, headerflags, TCP_WND);
111 }
112 
117 struct pbuf*
118 tcp_create_rx_segment(struct tcp_pcb* pcb, void* data, size_t data_len, u32_t seqno_offset,
119  u32_t ackno_offset, u8_t headerflags)
120 {
121  return tcp_create_segment(&pcb->remote_ip, &pcb->local_ip, pcb->remote_port, pcb->local_port,
122  data, data_len, pcb->rcv_nxt + seqno_offset, pcb->lastack + ackno_offset, headerflags);
123 }
124 
130 struct pbuf* tcp_create_rx_segment_wnd(struct tcp_pcb* pcb, void* data, size_t data_len,
131  u32_t seqno_offset, u32_t ackno_offset, u8_t headerflags, u16_t wnd)
132 {
133  return tcp_create_segment_wnd(&pcb->remote_ip, &pcb->local_ip, pcb->remote_port, pcb->local_port,
134  data, data_len, pcb->rcv_nxt + seqno_offset, pcb->lastack + ackno_offset, headerflags, wnd);
135 }
136 
138 void
139 tcp_set_state(struct tcp_pcb* pcb, enum tcp_state state, ip_addr_t* local_ip,
140  ip_addr_t* remote_ip, u16_t local_port, u16_t remote_port)
141 {
142  /* @todo: are these all states? */
143  /* @todo: remove from previous list */
144  pcb->state = state;
145  if (state == ESTABLISHED) {
146  TCP_REG(&tcp_active_pcbs, pcb);
147  pcb->local_ip.addr = local_ip->addr;
148  pcb->local_port = local_port;
149  pcb->remote_ip.addr = remote_ip->addr;
150  pcb->remote_port = remote_port;
151  } else if(state == LISTEN) {
152  TCP_REG(&tcp_listen_pcbs.pcbs, pcb);
153  pcb->local_ip.addr = local_ip->addr;
154  pcb->local_port = local_port;
155  } else if(state == TIME_WAIT) {
156  TCP_REG(&tcp_tw_pcbs, pcb);
157  pcb->local_ip.addr = local_ip->addr;
158  pcb->local_port = local_port;
159  pcb->remote_ip.addr = remote_ip->addr;
160  pcb->remote_port = remote_port;
161  } else {
162  fail();
163  }
164 }
165 
166 void
168 {
169  struct test_tcp_counters* counters = arg;
170  EXPECT_RET(arg != NULL);
171  counters->err_calls++;
172  counters->last_err = err;
173 }
174 
175 static void
177 {
178  struct pbuf* q;
179  u32_t i, received;
180  if(counters->expected_data == NULL) {
181  /* no data to compare */
182  return;
183  }
184  EXPECT_RET(counters->recved_bytes + p->tot_len <= counters->expected_data_len);
185  received = counters->recved_bytes;
186  for(q = p; q != NULL; q = q->next) {
187  char *data = q->payload;
188  for(i = 0; i < q->len; i++) {
189  EXPECT_RET(data[i] == counters->expected_data[received]);
190  received++;
191  }
192  }
193  EXPECT(received == counters->recved_bytes + p->tot_len);
194 }
195 
196 err_t
197 test_tcp_counters_recv(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t err)
198 {
199  struct test_tcp_counters* counters = arg;
200  EXPECT_RETX(arg != NULL, ERR_OK);
201  EXPECT_RETX(pcb != NULL, ERR_OK);
203 
204  if (p != NULL) {
205  if (counters->close_calls == 0) {
206  counters->recv_calls++;
208  counters->recved_bytes += p->tot_len;
209  } else {
210  counters->recv_calls_after_close++;
211  counters->recved_bytes_after_close += p->tot_len;
212  }
213  pbuf_free(p);
214  } else {
215  counters->close_calls++;
216  }
217  EXPECT(counters->recv_calls_after_close == 0 && counters->recved_bytes_after_close == 0);
218  return ERR_OK;
219 }
220 
222 struct tcp_pcb*
224 {
225  struct tcp_pcb* pcb = tcp_new();
226  if (pcb != NULL) {
227  /* set up args and callbacks */
228  tcp_arg(pcb, counters);
230  tcp_err(pcb, test_tcp_counters_err);
231  pcb->snd_wnd = TCP_WND;
232  pcb->snd_wnd_max = TCP_WND;
233  }
234  return pcb;
235 }
236 
238 void test_tcp_input(struct pbuf *p, struct netif *inp)
239 {
240  struct ip_hdr *iphdr = (struct ip_hdr*)p->payload;
241  /* these lines are a hack, don't use them as an example :-) */
242  ip_addr_copy(*ipX_current_dest_addr(), iphdr->dest);
243  ip_addr_copy(*ipX_current_src_addr(), iphdr->src);
244  ip_current_netif() = inp;
245  ip_current_header() = iphdr;
246 
247  /* since adding IPv6, p->payload must point to tcp header, not ip header */
248  pbuf_header(p, -(s16_t)sizeof(struct ip_hdr));
249 
250  tcp_input(p, inp);
251 
252  ipX_current_dest_addr()->addr = 0;
253  ipX_current_src_addr()->addr = 0;
256 }
257 
258 static err_t test_tcp_netif_output(struct netif *netif, struct pbuf *p,
259  ip_addr_t *ipaddr)
260 {
261  struct test_tcp_txcounters *txcounters = (struct test_tcp_txcounters*)netif->state;
262  LWIP_UNUSED_ARG(ipaddr);
263  if (txcounters != NULL)
264  {
265  txcounters->num_tx_calls++;
266  txcounters->num_tx_bytes += p->tot_len;
267  if (txcounters->copy_tx_packets) {
268  struct pbuf *p_copy = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM);
269  err_t err;
270  EXPECT(p_copy != NULL);
271  err = pbuf_copy(p_copy, p);
272  EXPECT(err == ERR_OK);
273  if (txcounters->tx_packets == NULL) {
274  txcounters->tx_packets = p_copy;
275  } else {
276  pbuf_cat(txcounters->tx_packets, p_copy);
277  }
278  }
279  }
280  return ERR_OK;
281 }
282 
283 void test_tcp_init_netif(struct netif *netif, struct test_tcp_txcounters *txcounters,
284  ip_addr_t *ip_addr, ip_addr_t *netmask)
285 {
286  struct netif *n;
287  memset(netif, 0, sizeof(struct netif));
288  if (txcounters != NULL) {
289  memset(txcounters, 0, sizeof(struct test_tcp_txcounters));
290  netif->state = txcounters;
291  }
296  for (n = netif_list; n != NULL; n = n->next) {
297  if (n == netif) {
298  return;
299  }
300  }
301  netif->next = NULL;
302  netif_list = netif;
303 }
struct pbuf * tx_packets
Definition: tcp_helper.h:26
struct tcp_pcb * test_tcp_new_counters_pcb(struct test_tcp_counters *counters)
Definition: tcp_helper.c:223
struct netif * netif_list
Definition: netif.c:75
#define ip_addr_copy(dest, src)
Definition: ip_addr.h:162
void test_tcp_init_netif(struct netif *netif, struct test_tcp_txcounters *txcounters, ip_addr_t *ip_addr, ip_addr_t *netmask)
Definition: tcp_helper.c:283
#define htonl(x)
Definition: module.h:212
STREAM tcp_recv(STREAM s, uint32 length)
Definition: tcp.c:344
struct pbuf * tcp_create_segment(ip_addr_t *src_ip, ip_addr_t *dst_ip, u16_t src_port, u16_t dst_port, void *data, size_t data_len, u32_t seqno, u32_t ackno, u8_t headerflags)
Definition: tcp_helper.c:105
void test_tcp_counters_err(void *arg, err_t err)
Definition: tcp_helper.c:167
#define ip_current_netif()
Definition: ip.h:194
#define NETIF_FLAG_UP
Definition: netif.h:69
GLint GLint GLsizei GLuint * counters
Definition: glext.h:11114
#define IPH_TOS_SET(hdr, tos)
Definition: ip.h:157
r received
Definition: btrfs.c:2864
GLdouble n
Definition: glext.h:7729
u8_t pbuf_header(struct pbuf *p, s16_t header_size_increment)
Definition: pbuf.c:511
u16_t inet_chksum_pseudo(struct pbuf *p, ip_addr_t *src, ip_addr_t *dest, u8_t proto, u16_t proto_len)
Definition: inet_chksum.c:272
typedefPACK_STRUCT_END struct ip_addr ip_addr_t
Definition: ip_addr.h:64
void * arg
Definition: msvc.h:12
netif_output_fn output
Definition: netif.h:151
struct pbuf * pbuf_alloc(pbuf_layer layer, u16_t length, pbuf_type type)
Definition: pbuf.c:207
#define IPH_VHL_SET(hdr, v, hl)
Definition: ip.h:156
Definition: pbuf.h:58
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
static err_t test_tcp_netif_output(struct netif *netif, struct pbuf *p, ip_addr_t *ipaddr)
Definition: tcp_helper.c:258
Definition: pbuf.h:53
static void tcp_remove(struct tcp_pcb *pcb_list)
Definition: tcp_helper.c:14
#define EXPECT_RET(x)
Definition: lwip_check.h:12
#define IP_PROTO_TCP
Definition: ip.h:56
#define TCP_WND
Definition: opt.h:923
smooth NULL
Definition: ftsmooth.c:416
u8_t pbuf_free(struct pbuf *p)
Definition: pbuf.c:618
s8_t err_t
Definition: err.h:47
Definition: pbuf.h:54
#define IP_HLEN
Definition: ip.h:50
err_t pbuf_copy(struct pbuf *p_to, struct pbuf *p_from)
Definition: pbuf.c:852
void tcp_remove_all(void)
Definition: tcp_helper.c:28
u16_t inet_chksum(void *dataptr, u16_t len)
Definition: inet_chksum.c:396
err_t pbuf_take(struct pbuf *buf, const void *dataptr, u16_t len)
Definition: pbuf.c:966
void tcp_set_state(struct tcp_pcb *pcb, enum tcp_state state, ip_addr_t *local_ip, ip_addr_t *remote_ip, u16_t local_port, u16_t remote_port)
Definition: tcp_helper.c:139
#define ERR_OK
Definition: err.h:52
struct netif * next
Definition: netif.h:138
Definition: pbuf.h:79
unsigned long u32_t
Definition: cc.h:25
u8_t flags
Definition: netif.h:192
void test_tcp_input(struct pbuf *p, struct netif *inp)
Definition: tcp_helper.c:238
Definition: pbuf.h:61
struct pbuf * tcp_create_rx_segment(struct tcp_pcb *pcb, void *data, size_t data_len, u32_t seqno_offset, u32_t ackno_offset, u8_t headerflags)
Definition: tcp_helper.c:118
#define EXPECT_RETNULL(x)
Definition: lwip_check.h:14
Definition: netif.h:136
#define ip_current_header()
Definition: ip.h:198
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
Definition: tcpdef.h:22
ip_addr_t ip_addr
Definition: netif.h:141
static int state
Definition: maze.c:121
struct ip_addr src dest
Definition: ip.h:96
#define err(...)
err_t test_tcp_counters_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
Definition: tcp_helper.c:197
Definition: ip.h:116
void * state
Definition: netif.h:172
void pbuf_cat(struct pbuf *h, struct pbuf *t)
Definition: pbuf.c:745
unsigned char u8_t
Definition: cc.h:23
static void test_tcp_counters_check_rxdata(struct test_tcp_counters *counters, struct pbuf *p)
Definition: tcp_helper.c:176
struct pbuf * tcp_create_rx_segment_wnd(struct tcp_pcb *pcb, void *data, size_t data_len, u32_t seqno_offset, u32_t ackno_offset, u8_t headerflags, u16_t wnd)
Definition: tcp_helper.c:130
#define IPH_CHKSUM_SET(hdr, chksum)
Definition: ip.h:163
__u16 dest
Definition: tcpdef.h:24
ip_addr_t netmask
Definition: netif.h:142
unsigned short u16_t
Definition: cc.h:24
#define EXPECT(a, b, c, d, e, f)
Definition: vartest.c:1303
GLfloat GLfloat p
Definition: glext.h:8902
#define htons(x)
Definition: module.h:213
#define EXPECT_RETX(x, y)
Definition: lwip_check.h:13
static struct pbuf * tcp_create_segment_wnd(ip_addr_t *src_ip, ip_addr_t *dst_ip, u16_t src_port, u16_t dst_port, void *data, size_t data_len, u32_t seqno, u32_t ackno, u8_t headerflags, u16_t wnd)
Definition: tcp_helper.c:41
#define memset(x, y, z)
Definition: compat.h:39
#define LWIP_UNUSED_ARG(x)
Definition: arch.h:73
#define IPH_LEN_SET(hdr, len)
Definition: ip.h:158
signed short s16_t
Definition: cc.h:29