?? tcp.lst
字號:
227 7 }
228 6 }
229 5 }
230 4 }
231 3 }
232 2 }
233 1 }
234
235
236
237
238 //------------------------------------------------------------------------
239 // This runs every 0.5 seconds. If the connection has had no activity
240 // it initiates closing the connection.
241 //
C51 COMPILER V6.23a TCP 04/01/2003 10:13:04 PAGE 5
242 //------------------------------------------------------------------------
243 void tcp_inactivity(void)
244 {
245 1 UCHAR idata nr;
246 1
247 1 // Look for active connections in the established state
248 1 for (nr = 0; nr < 5; nr++)
249 1 {
250 2 if ((conxn[nr].ipaddr != 0) &&
251 2 (conxn[nr].state == STATE_ESTABLISHED) &&
252 2 (conxn[nr].inactivity))
253 2 {
254 3 // Decrement the timer and see if it hit 0
255 3 conxn[nr].inactivity--;
256 3 if (conxn[nr].inactivity == 0)
257 3 {
258 4 // Inactivity timer has just timed out.
259 4 // Initiate close of connection
260 4 tcp_send((FLG_ACK | FLG_FIN), 20, nr);
261 4 conxn[nr].my_sequence++; // For my FIN
262 4 conxn[nr].state = STATE_FIN_WAIT_1;
263 4 if (debug) serial_send("TCP: Entered FIN_WAIT_1 state\r");
264 4 }
265 3 }
266 2 }
267 1 }
268
269
270
271 //------------------------------------------------------------------------
272 // This handles incoming TCP messages and manages the TCP state machine
273 // Note - both the SYN and FIN flags consume a sequence number.
274 // See "TCP/IP Illustrated, Volume 1" Sect 18.6 for info on TCP states
275 // See "TCP/IP Illustrated, Volume 1" Sect 17.3 for info on flags
276 //------------------------------------------------------------------------
277 void tcp_rcve(UCHAR xdata * inbuf, UINT len)
278 {
279 1 UCHAR idata i, j, nr;
280 1 UINT idata result, header_len, data_len;
281 1 TCP_HEADER xdata * tcp;
282 1 IP_HEADER xdata * ip;
283 1 ULONG idata sum;
284 1
285 1 // IP header is always 20 bytes so message starts at index 34
286 1 tcp = (TCP_HEADER xdata *)(inbuf + 34);
287 1 ip = (IP_HEADER xdata *)(inbuf + 14);
288 1
289 1 // Compute TCP checksum including 12 byte pseudoheader
290 1 // Sum source_ipaddr, dest_ipaddr, and entire TCP message
291 1 sum = (ULONG)cksum(inbuf + 26, 8 + len);
292 1
293 1 // Add in the rest of pseudoheader which is
294 1 // protocol id and TCP segment length
295 1 sum += (ULONG)0x0006;
296 1 sum += (ULONG)len;
297 1
298 1 // In case there was a carry, add it back around
299 1 result = (UINT)(sum + (sum >> 16));
300 1
301 1 if (result != 0xFFFF)
302 1 {
303 2 if (debug) serial_send("TCP: Error, bad cksum\r");
C51 COMPILER V6.23a TCP 04/01/2003 10:13:04 PAGE 6
304 2 return;
305 2 }
306 1
307 1 if (debug) serial_send("TCP: Msg rcvd with good cksum\r");
308 1
309 1 // See if message is for http server
310 1 if (tcp->dest_port != HTTP_PORT)
311 1 {
312 2 if (debug)
313 2 {
314 3 serial_send("TCP: Error, msg to port ");
315 3 memset(text, 0, 10);
316 3 itoa(tcp->dest_port, text, 10);
317 3 serial_send(text);
318 3 serial_send("\r");
319 3 }
320 2 tcp_send(FLG_RST, 20, NO_CONNECTION);
321 2 return;
322 2 }
323 1
324 1 // Capture sender's IP address and port number
325 1 sender_ipaddr = ip->source_ipaddr;
326 1 sender_tcpport = tcp->source_port;
327 1
328 1 // See if the TCP segment is from someone we are already
329 1 // connected to.
330 1 for (i=0; i < 5; i++)
331 1 {
332 2 if ((ip->source_ipaddr == conxn[i].ipaddr) &&
333 2 (tcp->source_port == conxn[i].port))
334 2 {
335 3 nr = i;
336 3 if (debug) serial_send("TCP: Rcvd msg from existing conxn\r");
337 3 break;
338 3 }
339 2 }
340 1
341 1 // If i = 5, we are not connected. If it is a SYN then assign
342 1 // a temporary conection to it for processing
343 1 if (i == 5)
344 1 {
345 2 if (tcp->flags & FLG_SYN)
346 2 {
347 3 // Find first unused connection (one with IP = 0)
348 3 for (j=0; j < 5; j++)
349 3 {
350 4 if (conxn[j].ipaddr == 0)
351 4 {
352 5 nr = j;
353 5 // Initialize new connection
354 5 conxn[nr].state = STATE_LISTEN;
355 5 break;
356 5 }
357 4 }
358 3
359 3 // If all connections are used then drop msg
360 3 if (j == 5) return;
361 3
362 3 if (debug)
363 3 {
364 4 serial_send("TCP: New connection ");
365 4 memset(text, 0, 10);
C51 COMPILER V6.23a TCP 04/01/2003 10:13:04 PAGE 7
366 4 itoa((UINT)nr, text, 10);
367 4 serial_send(text);
368 4 serial_send("\r");
369 4 }
370 3 }
371 2 }
372 1
373 1
374 1 // By now we should have a connection number in range of 0-4
375 1 // Do a check to avoid any chance of exceeding size of struct
376 1 if (nr > 4)
377 1 {
378 2 if (debug) serial_send("TCP: Error in assigning conxn number\r");
379 2 return;
380 2 }
381 1
382 1 // Eventually put in protection against wrapping sequence
383 1 // numbers, for now make the client start over if his
384 1 // sequence number is close to wrapping
385 1 if (tcp->sequence > 0xFFFFFF00L)
386 1 {
387 2 if (debug) serial_send("TCP: Rcvd a high sequence number\r");
388 2 conxn[nr].ipaddr = 0;
389 2 tcp_send(FLG_RST, 20, NO_CONNECTION);
390 2 return;
391 2 }
392 1
393 1 // Handle messages whose action is mostly independent of state
394 1 // such as RST, SYN, and segment with no ACK. That way the
395 1 // state machine below does not need to worry about it.
396 1 if (tcp->flags & FLG_RST)
397 1 {
398 2 // An RST does not depend on state at all. And it does
399 2 // not count as data so do not send an ACK here. Close
400 2 // connection
401 2 if (debug) serial_send("TCP: Rcvd a reset\r");
402 2 conxn[nr].ipaddr = 0;
403 2 return;
404 2 }
405 1
406 1 else if (tcp->flags & FLG_SYN)
407 1 {
408 2 // A SYN segment only makes sense if connection is in LISTEN
409 2 if ((conxn[nr].state != STATE_LISTEN) &&
410 2 (conxn[nr].state != STATE_CLOSED))
411 2 {
412 3 if (debug) serial_send("TCP: Error, rcvd bogus SYN\r");
413 3 conxn[nr].ipaddr = 0;
414 3 tcp_send(FLG_RST, 20, NO_CONNECTION);
415 3 return;
416 3 }
417 2 }
418 1
419 1 else if ((tcp->flags & FLG_ACK) == 0)
420 1 {
421 2 // Incoming segments except SYN or RST must have ACK bit set
422 2 // See TCP/IP Illustrated, Vol 2, Page 965
423 2 // Drop segment but do not send a reset
424 2 if (debug) serial_send("TCP: Error, rcvd segment has no ACK\r");
425 2 return;
426 2 }
427 1
C51 COMPILER V6.23a TCP 04/01/2003 10:13:04 PAGE 8
428 1 // Compute length of header including options, and from that
429 1 // compute length of actual data
430 1 header_len = (tcp->flags & 0xF000) >> 10;
431 1 data_len = len - header_len;
432 1
433 1
434 1
435 1 // Handle TCP state machine for this connection
436 1 switch (conxn[nr].state)
437 1 {
438 2 case STATE_CLOSED:
439 2 case STATE_LISTEN:
440 2
441 2 // If incoming segment contains SYN and no ACK, then handle
442 2 if ((tcp->flags & FLG_SYN) && ((tcp->flags & FLG_ACK) == 0))
443 2 {
444 3 // Capture his starting sequence number and generate
445 3 // my starting sequence number
446 3 // Fill in connection information
447 3 conxn[nr].ipaddr = ip->source_ipaddr;
448 3 conxn[nr].port = tcp->source_port;
449 3 conxn[nr].state = STATE_LISTEN;
450 3 conxn[nr].his_sequence = 1 + tcp->sequence;
451 3 conxn[nr].his_ack = tcp->ack_number;
452 3
453 3 // Use system clock for initial sequence number
454 3 EA = 0;
455 3 conxn[nr].my_sequence = initial_sequence_nr;
456 3 initial_sequence_nr += 64000L;
457 3 EA = 1;
458 3
459 3 // Send header options with the next message
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -