Subversion Repositories Kolibri OS

Rev

Rev 2877 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1763 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
2362 hidnplayr 3
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved.    ;;
1763 hidnplayr 4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  Part of the tcp/ip network stack for KolibriOS                 ;;
7
;;                                                                 ;;
8
;;   Written by hidnplayr@kolibrios.org                            ;;
9
;;                                                                 ;;
10
;;    Based on the code of 4.4BSD                                  ;;
11
;;                                                                 ;;
12
;;          GNU GENERAL PUBLIC LICENSE                             ;;
13
;;             Version 2, June 1991                                ;;
14
;;                                                                 ;;
15
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1733 hidnplayr 16
 
1763 hidnplayr 17
$Revision: 2882 $
1733 hidnplayr 18
 
2390 hidnplayr 19
macro   TCP_checksum IP1, IP2 {
1733 hidnplayr 20
 
21
;-------------
22
; Pseudoheader
23
 
2390 hidnplayr 24
        ; protocol type
25
        mov     edx, IP_PROTO_TCP
1733 hidnplayr 26
 
2390 hidnplayr 27
        ; source address
28
        add     dl, byte [IP1+1]
29
        adc     dh, byte [IP1+0]
30
        adc     dl, byte [IP1+3]
31
        adc     dh, byte [IP1+2]
1733 hidnplayr 32
 
2390 hidnplayr 33
        ; destination address
34
        adc     dl, byte [IP2+1]
35
        adc     dh, byte [IP2+0]
36
        adc     dl, byte [IP2+3]
37
        adc     dh, byte [IP2+2]
1733 hidnplayr 38
 
2390 hidnplayr 39
        ; size
40
        adc     dl, cl
41
        adc     dh, ch
1733 hidnplayr 42
 
2390 hidnplayr 43
        adc     edx, 0
44
 
1733 hidnplayr 45
;---------------------
46
; Real header and data
47
 
2390 hidnplayr 48
        push    esi
49
        call    checksum_1
50
        call    checksum_2
51
        pop     esi
1733 hidnplayr 52
 
2390 hidnplayr 53
}       ; returns in dx only
1733 hidnplayr 54
 
55
 
56
 
57
 
2390 hidnplayr 58
macro   TCP_sendseqinit ptr {
1733 hidnplayr 59
 
2390 hidnplayr 60
        push    edi                     ;;;; i dont like this static use of edi
61
        mov     edi, [ptr + TCP_SOCKET.ISS]
62
        mov     [ptr + TCP_SOCKET.SND_UP], edi
63
        mov     [ptr + TCP_SOCKET.SND_MAX], edi
64
        mov     [ptr + TCP_SOCKET.SND_NXT], edi
65
        mov     [ptr + TCP_SOCKET.SND_UNA], edi
66
        pop     edi
1733 hidnplayr 67
 
68
}
69
 
70
 
71
 
2390 hidnplayr 72
macro   TCP_rcvseqinit ptr {
1733 hidnplayr 73
 
2390 hidnplayr 74
        push    edi
75
        mov     edi, [ptr + TCP_SOCKET.IRS]
76
        inc     edi
77
        mov     [ptr + TCP_SOCKET.RCV_NXT], edi
78
        mov     [ptr + TCP_SOCKET.RCV_ADV], edi
79
        pop     edi
1733 hidnplayr 80
 
81
}
82
 
83
 
84
 
2612 hidnplayr 85
macro TCP_init_socket socket {
1733 hidnplayr 86
 
2612 hidnplayr 87
        mov     [socket + TCP_SOCKET.t_maxseg], TCP_mss_default
88
        mov     [socket + TCP_SOCKET.t_flags], 0                ; we could also request scale and timestamp
1733 hidnplayr 89
 
2612 hidnplayr 90
        mov     [socket + TCP_SOCKET.t_srtt], TCP_time_srtt_default
91
        mov     [socket + TCP_SOCKET.t_rttvar], TCP_time_rtt_default * 4
92
        mov     [socket + TCP_SOCKET.t_rttmin], TCP_time_re_min
93
;;; TODO: TCP_time_rangeset
1733 hidnplayr 94
 
2612 hidnplayr 95
        mov     [socket + TCP_SOCKET.SND_CWND], TCP_max_win shl TCP_max_winshift
96
        mov     [socket + TCP_SOCKET.SND_SSTHRESH], TCP_max_win shl TCP_max_winshift
1733 hidnplayr 97
 
98
 
2612 hidnplayr 99
}
1733 hidnplayr 100
 
101
 
102
;---------------------------
103
;
104
; TCP_pull_out_of_band
105
;
106
; IN:  eax =
107
;      ebx = socket ptr
108
;      edx = tcp packet ptr
109
;
110
; OUT: /
111
;
112
;---------------------------
113
 
114
align 4
115
TCP_pull_out_of_band:
116
 
2390 hidnplayr 117
        DEBUGF  1,"TCP_pull_out_of_band\n"
1733 hidnplayr 118
 
2390 hidnplayr 119
        ;;;; 1282-1305
1733 hidnplayr 120
 
2390 hidnplayr 121
        ret
1733 hidnplayr 122
 
123
 
124
 
125
 
126
 
127
 
128
 
129
 
130
;-------------------------
131
;
132
; TCP_drop
133
;
134
;  IN:  eax = socket ptr
135
;       ebx = error number
136
;
137
;  OUT: eax = socket ptr
138
;
139
;-------------------------
140
align 4
141
TCP_drop:
142
 
2390 hidnplayr 143
        DEBUGF  1,"TCP_drop\n"
1733 hidnplayr 144
 
2390 hidnplayr 145
        cmp     [eax + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED
146
        jb      .no_syn_received
1733 hidnplayr 147
 
2390 hidnplayr 148
        mov     [eax + TCP_SOCKET.t_state], TCPS_CLOSED
1733 hidnplayr 149
 
2390 hidnplayr 150
        call    TCP_output
1733 hidnplayr 151
 
152
;;; TODO: update stats
153
 
2390 hidnplayr 154
        jmp     TCP_close
1733 hidnplayr 155
 
156
  .no_syn_received:
157
 
158
;;; TODO: update stats
159
 
160
;;; TODO: check if error code is "Connection timed out' and handle accordingly
161
 
2390 hidnplayr 162
        mov     [eax + SOCKET.errorcode], ebx
1733 hidnplayr 163
 
164
 
165
 
166
 
167
 
168
 
169
 
170
 
171
;-------------------------
172
;
173
; TCP_close
174
;
175
;  IN:  eax = socket ptr
176
;  OUT: eax = socket ptr
177
;
178
;-------------------------
179
align 4
180
TCP_close:
181
 
2869 hidnplayr 182
        DEBUGF  1,"TCP_close: %x\n", eax
1733 hidnplayr 183
 
184
;;; TODO: update RTT and mean deviation
185
;;; TODO: update slow start threshold
186
 
2390 hidnplayr 187
        call    SOCKET_is_disconnected
1733 hidnplayr 188
 
2390 hidnplayr 189
        ret
1733 hidnplayr 190
 
191
 
192
 
2869 hidnplayr 193
;-------------------------
194
;
195
; TCP_disconnect
196
;
197
;  IN:  eax = socket ptr
198
;  OUT: eax = socket ptr
199
;
200
;-------------------------
201
align 4
202
TCP_disconnect:
1733 hidnplayr 203
 
2869 hidnplayr 204
        DEBUGF  1,"TCP_disconnect\n"
1733 hidnplayr 205
 
2869 hidnplayr 206
        cmp     [eax + TCP_SOCKET.t_state], TCPS_ESTABLISHED
207
        jb      TCP_close
1733 hidnplayr 208
 
209
 
2869 hidnplayr 210
; TODO: implement LINGER ?
1733 hidnplayr 211
 
2869 hidnplayr 212
        call    SOCKET_is_disconnecting
213
        call    TCP_usrclosed
214
        call    TCP_output
1733 hidnplayr 215
 
2869 hidnplayr 216
        ret
1733 hidnplayr 217
 
2869 hidnplayr 218
 
219
 
1733 hidnplayr 220
;-------------------------
221
;
2869 hidnplayr 222
; TCP_usrclose
223
;
224
;  IN:  eax = socket ptr
225
;
226
;-------------------------
227
align 4
228
TCP_usrclosed:
229
 
230
        push    ebx
231
        mov     ebx, [eax + TCP_SOCKET.t_state]
232
        mov     ebx, dword [.switch + ebx*4]
233
        jmp     ebx
234
 
235
  .switch:
236
 
237
        dd      .close                  ; TCPS_CLOSED
238
        dd      .close                  ; TCPS_LISTEN
239
        dd      .close                  ; TCPS_SYN_SENT
240
        dd      .wait1                  ; TCPS_SYN_RECEIVED
241
        dd      .wait1                  ; TCPS_ESTABLISHED
242
        dd      .last_ack               ; TCPS_CLOSE_WAIT
243
        dd      .ret                    ; TCPS_FIN_WAIT_1
244
        dd      .ret                    ; TCPS_CLOSING
245
        dd      .ret                    ; TCPS_LAST_ACK
246
        dd      .disc                   ; TCPS_FIN_WAIT_2
247
        dd      .disc                   ; TCPS_TIMED_WAIT
248
 
249
 
250
  .close:
251
        pop     ebx
252
        mov     [eax + TCP_SOCKET.t_state], TCPS_CLOSED
253
        call    TCP_close
254
        ret
255
 
256
  .wait1:
257
        pop     ebx
258
        mov     [eax + TCP_SOCKET.t_state], TCPS_FIN_WAIT_1
259
        ret
260
 
261
  .last_ack:
262
        pop     ebx
263
        mov     [eax + TCP_SOCKET.t_state], TCPS_LAST_ACK
264
        ret
265
 
266
  .disc:
267
        call    SOCKET_is_disconnected
268
  .ret:
269
        pop     ebx
270
        ret
271
 
272
 
273
;-------------------------
274
;
1733 hidnplayr 275
; TCP_outflags
276
;
277
;  IN:  eax = socket ptr
278
;
279
;  OUT: edx = flags
280
;
281
;-------------------------
282
align 4
283
TCP_outflags:
284
 
2390 hidnplayr 285
        mov     edx, [eax + TCP_SOCKET.t_state]
286
        movzx   edx, byte [edx + .flaglist]
1733 hidnplayr 287
 
2390 hidnplayr 288
        DEBUGF  1,"TCP_outflags, socket: %x, flags: %x\n", eax, dl
1733 hidnplayr 289
 
2390 hidnplayr 290
        ret
1733 hidnplayr 291
 
292
  .flaglist:
293
 
2390 hidnplayr 294
        db      TH_RST + TH_ACK         ; TCPS_CLOSED
295
        db      0                       ; TCPS_LISTEN
296
        db      TH_SYN                  ; TCPS_SYN_SENT
297
        db      TH_SYN + TH_ACK         ; TCPS_SYN_RECEIVED
298
        db               TH_ACK         ; TCPS_ESTABLISHED
299
        db               TH_ACK         ; TCPS_CLOSE_WAIT
300
        db      TH_SYN + TH_ACK         ; TCPS_FIN_WAIT_1
301
        db      TH_SYN + TH_ACK         ; TCPS_CLOSING
302
        db      TH_SYN + TH_ACK         ; TCPS_LAST_ACK
303
        db               TH_ACK         ; TCPS_FIN_WAIT_2
304
        db               TH_ACK         ; TCPS_TIMED_WAIT
1733 hidnplayr 305
 
306
 
307
 
308
 
309
 
310
 
311
;---------------------------------------
312
;
1830 hidnplayr 313
; The fast way to send an ACK/RST/keepalive segment
1733 hidnplayr 314
;
315
; TCP_respond_socket:
316
;
317
;  IN:  ebx = socket ptr
318
;        cl = flags
319
;
320
;--------------------------------------
321
align 4
322
TCP_respond_socket:
323
 
2390 hidnplayr 324
        DEBUGF  1,"TCP_respond_socket\n"
1733 hidnplayr 325
 
326
;---------------------
327
; Create the IP packet
328
 
2390 hidnplayr 329
        push    cx ebx
330
        mov     eax, [ebx + IP_SOCKET.RemoteIP]
2877 hidnplayr 331
        mov     edx, [ebx + IP_SOCKET.LocalIP]
2390 hidnplayr 332
        mov     ecx, sizeof.TCP_header
2877 hidnplayr 333
        mov     di, IP_PROTO_TCP shl 8 + 128
2390 hidnplayr 334
        call    IPv4_output
335
        test    edi, edi
336
        jz      .error
337
        pop     esi cx
338
        push    edx eax
1733 hidnplayr 339
 
340
;-----------------------------------------------
341
; Fill in the TCP header by using the socket ptr
342
 
2390 hidnplayr 343
        mov     ax, [esi + TCP_SOCKET.LocalPort]
344
        rol     ax, 8
345
        stosw
346
        mov     ax, [esi + TCP_SOCKET.RemotePort]
347
        rol     ax, 8
348
        stosw
349
        mov     eax, [esi + TCP_SOCKET.SND_NXT]
350
        bswap   eax
351
        stosd
352
        mov     eax, [esi + TCP_SOCKET.RCV_NXT]
353
        bswap   eax
354
        stosd
355
        mov     al, 0x50        ; Dataoffset: 20 bytes (TCP_header.DataOffset)
356
        stosb
357
        mov     al, cl
358
        stosb
1830 hidnplayr 359
;        mov     ax, [esi + TCP_SOCKET.RCV_WND]
360
;        rol     ax, 8
2390 hidnplayr 361
        mov     ax, 0x00a0      ;;;;;;; FIXME
362
        stosw                   ; window
363
        xor     eax, eax
364
        stosd                   ; checksum + urgentpointer
1733 hidnplayr 365
 
366
;---------------------
367
; Fill in the checksum
368
 
369
  .checksum:
2390 hidnplayr 370
        sub     edi, sizeof.TCP_header
371
        mov     ecx, sizeof.TCP_header
372
        xchg    esi, edi
373
        TCP_checksum (edi + IP_SOCKET.LocalIP), (edi + IP_SOCKET.RemoteIP)
374
        mov     [esi+TCP_header.Checksum], dx
1733 hidnplayr 375
 
376
;--------------------
377
; And send the segment
378
 
2390 hidnplayr 379
        call    [ebx + NET_DEVICE.transmit]
380
        ret
1733 hidnplayr 381
 
382
  .error:
2390 hidnplayr 383
        DEBUGF  1,"TCP_respond failed\n"
384
        add     esp, 2+4
1733 hidnplayr 385
 
2390 hidnplayr 386
        ret
1733 hidnplayr 387
 
388
 
389
 
390
 
391
 
392
 
393
 
394
 
395
;-------------------------
396
; TCP_respond.segment:
397
;
2600 hidnplayr 398
;  IN:  edx = segment ptr (a previously received segment)
2308 hidnplayr 399
;       edi = ptr to dest and src IPv4 addresses
1733 hidnplayr 400
;        cl = flags
401
 
402
align 4
403
TCP_respond_segment:
404
 
2390 hidnplayr 405
        DEBUGF  1,"TCP_respond_segment\n"
1733 hidnplayr 406
 
407
;---------------------
408
; Create the IP packet
409
 
2600 hidnplayr 410
        push    cx edx
2390 hidnplayr 411
        mov     ebx, [edi + 4]
412
        mov     eax, [edi]
413
        mov     ecx, sizeof.TCP_header
414
        mov     di , IP_PROTO_TCP shl 8 + 128
415
        call    IPv4_output
416
        jz      .error
2600 hidnplayr 417
        pop     esi cx
1733 hidnplayr 418
 
2390 hidnplayr 419
        push    edx eax
1733 hidnplayr 420
 
421
;---------------------------------------------------
422
; Fill in the TCP header by using a received segment
423
 
2390 hidnplayr 424
        mov     ax, [esi + TCP_header.DestinationPort]
425
        rol     ax, 8
426
        stosw
427
        mov     ax, [esi + TCP_header.SourcePort]
428
        rol     ax, 8
429
        stosw
430
        mov     eax, [esi + TCP_header.AckNumber]
431
        bswap   eax
432
        stosd
433
        xor     eax, eax
434
        stosd
435
        mov     al, 0x50        ; Dataoffset: 20 bytes (sizeof.TCP_header)
436
        stosb
437
        mov     al, cl
438
        stosb
439
        mov     ax, 1280
440
        rol     ax, 8
441
        stosw                   ; window
442
        xor     eax, eax
443
        stosd                   ; checksum + urgentpointer
1733 hidnplayr 444
 
445
;---------------------
446
; Fill in the checksum
447
 
448
  .checksum:
2390 hidnplayr 449
        lea     esi, [edi - sizeof.TCP_header]
450
        mov     ecx, sizeof.TCP_header
451
        TCP_checksum (esi - sizeof.IPv4_header + IPv4_header.DestinationAddress),\      ; FIXME
452
                     (esi - sizeof.IPv4_header + IPv4_header.SourceAddress)
453
        mov     [esi+TCP_header.Checksum], dx
1733 hidnplayr 454
 
455
;--------------------
456
; And send the segment
457
 
2390 hidnplayr 458
        call    [ebx + NET_DEVICE.transmit]
459
        ret
1733 hidnplayr 460
 
461
  .error:
2390 hidnplayr 462
        DEBUGF  1,"TCP_respond failed\n"
463
        add     esp, 2+4
1733 hidnplayr 464
 
2390 hidnplayr 465
        ret
2362 hidnplayr 466
 
467
 
468
 
469
macro TCP_set_persist socket {
470
 
471
;int t = ((tp->t_srtt >> 2) + tp->t_rttvar) >> 1;
472
;int tt;
473
;
474
;tp->t_flags &= ~TF_PREVVALID;
475
;
476
;if (tcp_timer_active(tp, TT_REXMT))
477
;        panic("tcp_setpersist: retransmit pending");
478
;
479
;; Start/restart persistance timer.
480
;
481
;TCPT_RANGESET(tt, t * tcp_backoff[tp->t_rxtshift], TCPTV_PERSMIN, TCPTV_PERSMAX);
482
;tcp_timer_activate(tp, TT_PERSIST, tt);
483
;
484
;if (tp->t_rxtshift < TCP_MAXRXTSHIFT)
485
;        tp->t_rxtshift++;
486
 
2612 hidnplayr 487
}