Subversion Repositories Kolibri OS

Rev

Rev 323 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
261 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;
3
;;  SOCKET.INC
4
;;
5
;;  Sockets constants, structures and functions
6
;;
7
;;  Last revision: 11.11.2006
8
;;
9
;;  This file contains the following:
10
;;    is_localport_unused
11
;;    get_free_socket
12
;;    socket_open
13
;;    socket_open_tcp
14
;;    socket_close
15
;;    socket_close_tcp
16
;;    socket_poll
17
;;    socket_status
18
;;    socket_read
19
;;    socket_write
20
;;    socket_write_tcp
21
;;
22
;;
23
;;  Changes history:
24
;;   22.09.2003 - [Mike Hibbett] : mikeh@oceanfree.net
25
;;   11.11.2006 - [Johnny_B] and [smb]
26
;;
27
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
28
 
29
;
30
;  Socket Descriptor + Buffer
31
;
32
;    0                   1                   2                   3
33
;    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
34
;
35
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
36
;  0|                    Status ( of this buffer )                  |
37
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
38
;  4|  Application Process ID                                       |
39
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
40
;  8|                  Local IP Address                             |
41
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
42
; 12| Local IP Port                 | Unused ( set to 0 )           |
43
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
44
; 16|                  Remote IP Address                            |
45
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
46
; 20| Remote IP Port                | Unused ( set to 0 )           |
47
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
48
; 24|   Rx Data Count                                   INTEL format|
49
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
50
; 28|                 TCB STATE                         INTEL format|
51
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
52
; 32|   TCB Timer (seconds)                             INTEL format|
53
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
54
; 36| ISS (Inital Sequence # used by this connection )   INET format|
55
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
56
; 40| IRS ( Inital Receive Sequence # )                  INET format|
57
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
58
; 44| SND.UNA  Seq # of unack'ed sent packets            INET format|
59
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
60
; 48| SND.NXT  Next send seq # to use                    INET format|
61
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
62
; 52| SND.WND  Send window                               INET format|
63
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
64
; 56| RCV.NXT  Next expected receive sequence #          INET format|
65
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
66
; 60| RCV.WND  Receive window                            INET format|
67
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
68
; 64| SEG.LEN  Segment length                           INTEL format|
69
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
70
; 68| SEG.WND  Segment window                           INTEL format|
71
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
72
; 72| Retransmit queue # NOW WINDOW SIZE TIMER          INTEL format|
73
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
74
; 76|      RX offset from
75
; 76|       RX Data                                                 |
76
;   +-+-+-..........                                               -+
77
 
78
 
79
; so, define struct
80
struc SOCKET
81
{  .Status                  dd   ?  ;+00 - Status ( of this buffer )
82
   .PID                     dd   ?  ;+04 - Application Process ID
83
   .LocalIP                 dd   ?  ;+08 -  Local IP Address
84
   .LocalPort               dw   ?  ;+12 - Local Port
85
   .UnusedL                 dw   ?  ;+14 - may be removed in future
86
   .RemoteIP                dd   ?  ;+16 - Remote IP Address
87
   .RemotePort              dw   ?  ;+20 - Remote Port
88
   .UnusedR                 dw   ?  ;+22 - may be removed in future
89
   .rxDataCount             dd   ?  ;+24 - Rx Data Count
90
   .TCBState                dd   ?  ;+28 - TCB STATE
91
   .TCBTimer                dd   ?  ;+32 - TCB Timer (seconds)
92
   .ISS                     dd   ?  ;+36 - Initial Send Sequence
93
   .IRS                     dd   ?  ;+40 - Initial Receive Sequence
94
   .SND_UNA                 dd   ?  ;+44 - Sequence number of unack'ed sent packets
95
   .SND_NXT                 dd   ?  ;+48 - Next send sequence number to use
96
   .SND_WND                 dd   ?  ;+52 - Send window
97
   .RCV_NXT                 dd   ?  ;+56 - Next receive sequence number to use
98
   .RCV_WND                 dd   ?  ;+60 - Receive window
99
   .SEG_LEN                 dd   ?  ;+64 - Segment length
100
   .SEG_WND                 dd   ?  ;+68 - Segment window
101
   .wndsizeTimer            dd   ?  ;+72 - Retransmit queue # NOW WINDOW SIZE TIMER
102
   .rxData                  dd   ?  ;+76 - receive data buffer here
103
}
104
 
105
virtual at 0
106
  SOCKET SOCKET
107
end virtual
108
 
109
; simple macro calcing real memory address of SOCKET struct by socket's
110
macro	Index2RealAddr reg
111
{
112
	shl     reg, 12
113
    add     reg, sockets
114
}
115
 
116
;Constants
117
; current socket statuses
118
SOCK_EMPTY         equ     0        ; socket not in use
119
SOCK_OPEN          equ     1        ; open issued, but no data sent
120
 
121
; TCP opening modes
122
SOCKET_PASSIVE     equ     0
123
SOCKET_ACTIVE      equ     1
124
 
125
;***************************************************************************
126
;   Function
127
;      is_localport_unused
128
;
129
;   Description
130
;         scans through all the active sockets , looking to see if the
131
;      port number specified in bx is in use as a localport number.
132
;      This is useful when you want a to generate a unique local port
133
;      number.
134
;          On return, eax = 1 for free, 0 for in use
135
;
136
;***************************************************************************
137
is_localport_unused:
138
    mov     al, bh
139
    mov     ah, bl
140
    mov     bx, ax
141
 
142
    mov     edx, SOCKETBUFFSIZE * NUM_SOCKETS
143
    mov     ecx, NUM_SOCKETS
144
    mov     eax, 0                    ; Assume the return value is 'in use'
145
 
146
ilu1:
147
    sub     edx, SOCKETBUFFSIZE
148
    cmp     [edx + sockets + SOCKET.LocalPort], bx
149
    loopnz  ilu1                  ; Return back if the socket is occupied
150
 
151
    jz      ilu_exit
152
    inc     eax                         ; return port not in use
153
 
154
ilu_exit:
155
    ret
156
 
157
 
158
 
159
;***************************************************************************
160
;   Function
161
;      get_free_socket
162
;
163
;   Description
164
;
165
;***************************************************************************
166
get_free_socket:
167
    push    ecx
168
    mov     eax, SOCKETBUFFSIZE * NUM_SOCKETS
169
    mov     ecx, NUM_SOCKETS
170
 
171
gfs1:
172
    sub     eax, SOCKETBUFFSIZE
173
    cmp     [eax + sockets + SOCKET.Status], dword SOCK_EMPTY
174
    loopnz  gfs1                  ; Return back if the socket is occupied
175
    mov     eax, ecx
176
    pop     ecx
177
    jz      gfs_exit
178
    mov     eax, 0xFFFFFFFF
179
 
180
gfs_exit:
181
    ret
182
 
183
 
184
;***************************************************************************
185
;   Function
186
;      socket_open
187
;
188
;   Description
189
;       find a free socket
190
;       local port in ebx
191
;       remote port in ecx
192
;       remote ip in edx
193
;       return socket # in eax, -1 if none available
194
;
195
;***************************************************************************
196
socket_open:
197
    call    get_free_socket
198
 
199
    cmp     eax, 0xFFFFFFFF
200
    jz      so_exit
201
 
202
    ; ax holds the socket number that is free. Get real address
203
    push    eax
204
    Index2RealAddr eax
205
 
206
    mov     [eax + SOCKET.Status], dword SOCK_OPEN
207
 
208
	xchg	bh, bl
209
	mov     [eax + SOCKET.LocalPort], bx
210
;    mov     [eax + 12], byte bh      ; Local port ( LS 16 bits )
211
;    mov     [eax + 13], byte bl      ; Local port ( LS 16 bits )
212
	xchg    ch, cl
213
	mov     [eax + SOCKET.RemotePort], cx
214
;    mov     [eax + 20], ch         ; Remote Port ( LS 16 bits )
215
;    mov     [eax + 21], cl         ; Remote Port ( LS 16 bits )
216
 
217
    mov     ebx, [stack_ip]
218
    mov     [eax + SOCKET.LocalIP], ebx
219
    mov     [eax + SOCKET.RemoteIP], edx
220
    mov     [eax + SOCKET.rxDataCount], dword 0      ; recieved data count
221
 
222
    mov     esi, [0x3010]
223
    mov     ebx, [esi+TASKDATA.pid]
224
    mov     [eax + SOCKET.PID], ebx         ; save the process ID
225
    pop     eax      ; Get the socket number back, so we can return it
226
 
227
so_exit:
228
    ret
229
 
230
 
231
 
232
;***************************************************************************
233
;   Function
234
;      socket_open_tcp
235
;
236
;   Description
237
;       Opens a TCP socket in PASSIVE or ACTIVE mode
238
;       find a free socket
239
;       local port in ebx ( intel format )
240
;       remote port in ecx ( intel format )
241
;       remote ip in edx ( in Internet byte order )
242
;       Socket open mode in esi  ( SOCKET_PASSIVE or SOCKET_ACTIVE )
243
;       return socket # in eax, -1 if none available
244
;
245
;***************************************************************************
246
socket_open_tcp:
247
    call    get_free_socket
248
 
249
    cmp     eax, 0xFFFFFFFF
250
    jz      so_exit
251
 
252
    ; ax holds the socket number that is free. Get real address
253
    push eax
254
    Index2RealAddr eax
255
 
256
    mov     [sktAddr], eax
257
    mov     [eax], dword SOCK_OPEN
258
 
259
    ; TODO - check this works!
260
    mov     [eax + SOCKET.wndsizeTimer], dword 0     ; Reset the window timer.
261
 
262
	xchg    bh, bl
263
	mov     [eax + SOCKET.LocalPort], bx
264
;    mov     [eax + 12], byte bh      ; Local port ( LS 16 bits )
265
;    mov     [eax + 13], byte bl      ; Local port ( LS 16 bits )
266
 
267
	xchg    ch, cl
268
	mov     [eax + SOCKET.RemotePort], cx
269
;    mov     [eax + 20], ch         ; Remote Port ( LS 16 bits )
270
;    mov     [eax + 21], cl         ; Remote Port ( LS 16 bits )
271
 
272
    mov     ebx, [stack_ip]
273
    mov     [eax + SOCKET.LocalIP], ebx
274
    mov     [eax + SOCKET.RemoteIP], edx
275
    mov     [eax + SOCKET.rxDataCount], dword 0
276
 
277
    ; Now fill in TCB state
278
    mov     ebx, TCB_LISTEN
279
    cmp     esi, SOCKET_PASSIVE
280
    jz      sot_001
281
    mov     ebx, TCB_SYN_SENT
282
 
283
sot_001:
284
    mov     [eax + SOCKET.TCBState], ebx            ; Indicate the state of the TCB
285
 
286
    mov     esi, [0x3010]
287
    mov     ecx, [esi+TASKDATA.pid]
288
    mov     [eax + SOCKET.PID], ecx         ; save the process ID
289
 
290
    cmp     ebx, TCB_LISTEN
291
    je      sot_done
292
 
293
    ; Now, if we are in active mode, then we have to send a SYN to the specified remote port
294
    mov     eax, EMPTY_QUEUE
295
    call    dequeue
296
    cmp     ax, NO_BUFFER
297
    je      sot_done
298
 
299
    push    eax
300
 
301
    mov     bl, 0x02        ; SYN
302
    mov     ecx, 0
303
 
304
    call    buildTCPPacket
305
 
306
    mov     eax, NET1OUT_QUEUE
307
 
308
    mov     edx, [stack_ip]
309
    mov     ecx, [sktAddr ]
310
    mov     ecx, [ecx + 16]
311
    cmp     edx, ecx
312
    jne     sot_notlocal
313
    mov     eax, IPIN_QUEUE
314
 
315
sot_notlocal:
316
       ; Send it.
317
    pop     ebx
318
    call    queue
319
 
320
    mov     esi, [sktAddr]
321
 
322
    ; increment SND.NXT in socket
323
    add     esi, 48
324
    call    inc_inet_esi
325
 
326
sot_done:
327
    pop     eax      ; Get the socket number back, so we can return it
328
 
329
sot_exit:
330
    ret
331
 
332
 
333
 
334
;***************************************************************************
335
;   Function
336
;      socket_close
337
;
338
;   Description
339
;       socket # in ebx
340
;       returns 0 for ok, -1 for socket not open (fail)
341
;
342
;***************************************************************************
343
socket_close:
344
    Index2RealAddr ebx
345
    mov     eax, 0xFFFFFFFF         ; assume this operation will fail..
346
    cmp     [ebx + SOCKET.Status], dword SOCK_EMPTY
347
    jz      sc_exit
348
 
349
    ; Clear the socket varaibles
350
    xor     eax, eax
351
    mov     edi, ebx
352
    mov     ecx, SOCKETHEADERSIZE
353
    cld
354
    rep     stosb
355
 
356
sc_exit:
357
    ret
358
 
359
 
360
 
361
;***************************************************************************
362
;   Function
363
;      socket_close_tcp
364
;
365
;   Description
366
;       socket # in ebx
367
;       returns 0 for ok, -1 for socket not open (fail)
368
;
369
;***************************************************************************
370
socket_close_tcp:
371
    ; first, remove any resend entries
372
    pusha
373
 
374
    mov     esi, resendQ
375
    mov     ecx, 0
376
 
377
sct001:
378
    cmp     ecx, NUMRESENDENTRIES
379
    je      sct003              ; None left
380
    cmp     [esi], bl
381
    je      sct002              ; found one
382
    inc     ecx
383
    add     esi, 4
384
    jmp     sct001
385
 
386
sct002:
387
 
388
    mov     [esi], byte 0xFF
389
    jmp     sct001
390
 
391
sct003:
392
    popa
393
 
394
    Index2RealAddr ebx
395
    mov     [sktAddr], ebx
396
    mov     eax, 0xFFFFFFFF         ; assume this operation will fail..
397
    cmp     [ebx + SOCKET.Status], dword SOCK_EMPTY
398
    jz      sct_exit
399
 
400
    ; Now construct the response, and queue for sending by IP
401
    mov     eax, EMPTY_QUEUE
402
    call    dequeue
403
    cmp     ax, NO_BUFFER
404
    je      stl_exit
405
 
406
    push    eax
407
 
408
    mov     bl, 0x11        ; FIN + ACK
409
    mov     ecx, 0
410
    mov     esi, 0
411
 
412
    call    buildTCPPacket
413
 
414
    mov     ebx, [sktAddr]
415
 
416
    ; increament SND.NXT in socket
417
    mov     esi, 48
418
    add     esi, ebx
419
    call    inc_inet_esi
420
 
421
 
422
    ; Get the socket state
423
    mov     eax, [ebx + SOCKET.TCBState]
424
    cmp     eax, TCB_LISTEN
425
    je      destroyTCB
426
    cmp     eax, TCB_SYN_SENT
427
    je      destroyTCB
428
    cmp     eax, TCB_SYN_RECEIVED
429
    je      sct_finwait1
430
    cmp     eax, TCB_ESTABLISHED
431
    je      sct_finwait1
432
 
433
    ; assume CLOSE WAIT
434
    ; Send a fin, then enter last-ack state
435
    mov     eax, TCB_LAST_ACK
436
    mov     [ebx + SOCKET.TCBState], eax
437
    xor     eax, eax
438
    jmp     sct_send
439
 
440
sct_finwait1:
441
    ; Send a fin, then enter finwait2 state
442
    mov     eax, TCB_FIN_WAIT_1
443
    mov     [ebx + SOCKET.TCBState], eax
444
    xor     eax, eax
445
 
446
sct_send:
447
    mov     eax, NET1OUT_QUEUE
448
 
449
    mov     edx, [stack_ip]
450
    mov     ecx, [sktAddr ]
451
    mov     ecx, [ecx + 16]
452
    cmp     edx, ecx
453
    jne     sct_notlocal
454
    mov     eax, IPIN_QUEUE
455
 
456
sct_notlocal:
457
       ; Send it.
458
    pop     ebx
459
    call    queue
460
    jmp     sct_exit
461
 
462
destroyTCB:
463
    pop     eax
464
    ; Clear the socket varaibles
465
    xor     eax, eax
466
    mov     edi, ebx
467
    mov     ecx, SOCKETHEADERSIZE
468
    cld
469
    rep     stosb
470
 
471
sct_exit:
472
    ret
473
 
474
 
475
 
476
;***************************************************************************
477
;   Function
478
;      socket_poll
479
;
480
;   Description
481
;       socket # in ebx
482
;       returns count in eax.
483
;
484
;***************************************************************************
485
socket_poll:
486
    Index2RealAddr ebx
487
    mov     eax, [ebx + SOCKET.rxDataCount]
488
 
489
    ret
490
 
491
 
492
 
493
;***************************************************************************
494
;   Function
495
;      socket_status
496
;
497
;   Description
498
;       socket # in ebx
499
;       returns TCB state in eax.
500
;
501
;***************************************************************************
502
socket_status:
503
    Index2RealAddr ebx
504
    mov     eax, [ebx + SOCKET.TCBState]
505
 
506
    ret
507
 
508
 
509
 
510
;***************************************************************************
511
;   Function
512
;      socket_read
513
;
514
;   Description
515
;       socket # in ebx
516
;       returns # of bytes remaining in eax, data in bl
517
;
518
;***************************************************************************
519
socket_read:
520
    Index2RealAddr ebx
521
    mov     eax, [ebx + SOCKET.rxDataCount]         ; get count of bytes
522
    mov     ecx, 1
523
    test    eax, eax
524
    jz      sr2
525
 
526
    dec     eax
527
    mov     esi, ebx            ; esi is address of socket
528
    mov     [ebx + SOCKET.rxDataCount], eax         ; store new count
529
    ;movzx   ebx, byte [ebx + SOCKET.rxData]  ; get the byte
530
    movzx   ebx, byte [ebx + SOCKETHEADERSIZE]  ; get the byte
531
    add     esi, SOCKETHEADERSIZE
532
    mov     edi, esi
533
    inc     esi
534
 
535
    mov     ecx, (SOCKETBUFFSIZE - SOCKETHEADERSIZE) / 4
536
    cld
537
    rep     movsd
538
    xor     ecx, ecx
539
 
540
sr1:
541
    jmp     sor_exit
542
 
543
sr2:
544
    xor     bl, bl
545
 
546
sor_exit:
547
    ret
548
 
549
 
550
 
551
;***************************************************************************
552
;   Function
553
;      socket_write
554
;
555
;   Description
556
;       socket in ebx
557
;       # of bytes to write in ecx
558
;       pointer to data in edx
559
;       returns 0 in eax ok, -1 == failed ( invalid socket, or
560
;       could not queue IP packet )
561
;
562
;***************************************************************************
563
socket_write:
564
    Index2RealAddr ebx
565
 
566
    mov     eax, 0xFFFFFFFF
567
    ; If the socket is invalid, return with an error code
568
    cmp     [ebx], dword SOCK_EMPTY
569
    je      sw_exit
570
 
571
 
572
    mov     eax, EMPTY_QUEUE
573
    call    dequeue
574
    cmp     ax, NO_BUFFER
575
    je      sw_exit
576
 
577
    ; Save the queue entry number
578
    push    eax
579
 
580
    ; save the pointers to the data buffer & size
581
    push    edx
582
    push    ecx
583
 
584
    ; convert buffer pointer eax to the absolute address
585
    mov     ecx, IPBUFFSIZE
586
    mul     ecx
587
    add     eax, IPbuffs
588
 
589
    mov     edx, eax
590
 
591
    ; So, ebx holds the socket ptr, edx holds the IPbuffer ptr
592
 
593
    ; Fill in the IP header ( some data is in the socket descriptor)
594
    mov     eax, [ebx + 8]
595
    mov     [edx + 12], eax      ; source IP
596
    mov     eax, [ebx + 16]
597
    mov     [edx + 16], eax      ; Destination IP
598
 
599
    mov     al, 0x45
600
    mov     [edx], al         ; Version, IHL
601
    xor     al, al
602
    mov     [edx + 1], al     ; Type of service
603
 
604
    pop     eax                   ; Get the UDP data length
605
    push    eax
606
 
607
    add     eax, 20 + 8           ; add IP header and UDP header lengths
608
    mov     [edx + 2], ah
609
    mov     [edx + 3], al
610
    xor     al, al
611
    mov     [edx + 4], al
612
    mov     [edx + 5], al
613
    mov     al, 0x40
614
    mov     [edx + 6], al
615
    xor     al, al
616
    mov     [edx + 7], al
617
    mov     al, 0x20
618
    mov     [edx + 8], al
619
    mov     al, 17
620
    mov     [edx + 9], al
621
 
622
    ; Checksum left unfilled
623
    xor     ax, ax
624
    mov     [edx + 10], ax
625
 
626
    ; Fill in the UDP header ( some data is in the socket descriptor)
627
    mov     ax, [ebx + 12]
628
    mov     [edx + 20], ax
629
 
630
    mov     ax, [ebx + 20]
631
    mov     [edx + 20 + 2], ax
632
 
633
    pop     eax
634
    push    eax
635
 
636
    add     eax, 8
637
    mov     [edx + 20 + 4], ah
638
    mov     [edx + 20 + 5], al
639
 
640
    ; Checksum left unfilled
641
    xor     ax, ax
642
    mov     [edx + 20 + 6], ax
643
 
644
    pop     ecx                  ; count of bytes to send
645
    mov     ebx, ecx            ; need the length later
646
    pop     eax                  ; get callers ptr to data to send
647
 
648
    ; Get the address of the callers data
649
    mov     edi, [0x3010]
650
    add     edi, TASKDATA.mem_start
651
    add     eax, [edi]
652
    mov     esi, eax
653
 
654
    mov     edi, edx
655
    add     edi, 28
656
    cld
657
    rep     movsb               ; copy the data across
658
 
659
    ; we have edx as IPbuffer ptr.
660
    ; Fill in the UDP checksum
661
    ; First, fill in pseudoheader
662
    mov     eax, [edx + 12]
663
    mov     [pseudoHeader], eax
664
    mov     eax, [edx + 16]
665
    mov     [pseudoHeader+4], eax
666
    mov     ax, 0x1100            ; 0 + protocol
667
    mov     [pseudoHeader+8], ax
668
    add     ebx, 8
669
    mov     eax, ebx
670
    mov     [pseudoHeader+10], ah
671
    mov     [pseudoHeader+11], al
672
 
673
    mov     eax, pseudoHeader
674
    mov     [checkAdd1], eax
675
    mov     [checkSize1], word 12
676
    mov     eax, edx
677
    add     eax, 20
678
    mov     [checkAdd2], eax
679
    mov     eax, ebx
680
    mov     [checkSize2], ax      ; was eax!! mjh 8/7/02
681
 
682
    call    checksum
683
 
684
    ; store it in the UDP checksum ( in the correct order! )
685
    mov     ax, [checkResult]
686
 
687
    ; If the UDP checksum computes to 0, we must make it 0xffff
688
    ; (0 is reserved for 'not used')
689
    cmp     ax, 0
690
    jne     sw_001
691
    mov     ax, 0xffff
692
 
693
sw_001:
694
    mov     [edx + 20 + 6], ah
695
    mov     [edx + 20 + 7], al
696
 
697
    ; Fill in the IP header checksum
698
    GET_IHL ecx,edx              ; get IP-Header length
699
    stdcall checksum_jb,edx,ecx  ; buf_ptr, buf_size
700
 
701
    mov     [edx + 10], ah
702
    mov     [edx + 11], al
703
 
704
    ; Check destination IP address.
705
    ; If it is the local host IP, route it back to IP_RX
706
 
707
    pop     ebx
708
    mov     eax, NET1OUT_QUEUE
709
 
710
    mov     ecx, [ edx + 16]
711
    mov     edx, [stack_ip]
712
    cmp     edx, ecx
713
    jne     sw_notlocal
714
    mov     eax, IPIN_QUEUE
715
 
716
sw_notlocal:
717
    ; Send it.
718
    call    queue
719
 
720
    xor     eax, eax
721
 
722
sw_exit:
723
    ret
724
 
725
 
726
 
727
;***************************************************************************
728
;   Function
729
;      socket_write_tcp
730
;
731
;   Description
732
;       socket in ebx
733
;       # of bytes to write in ecx
734
;       pointer to data in edx
735
;       returns 0 in eax ok, -1 == failed ( invalid socket, or
736
;       could not queue IP packet )
737
;
738
;***************************************************************************
739
socket_write_tcp:
740
	Index2RealAddr ebx
741
 
742
    mov     [sktAddr], ebx
743
 
744
    mov     eax, 0xFFFFFFFF
745
    ; If the socket is invalid, return with an error code
746
    cmp     [ebx], dword SOCK_EMPTY
747
    je      swt_exit
748
 
749
    ; If the sockets window timer is nonzero, do not queue packet
750
    ; TODO - done
751
    cmp     [ebx + SOCKET.wndsizeTimer], dword 0
752
    jne     swt_exit
753
 
754
    mov     eax, EMPTY_QUEUE
755
    call    dequeue
756
    cmp     ax, NO_BUFFER
757
    je      swt_exit
758
 
759
    push    eax
760
 
761
    mov     bl, 0x10        ; ACK
762
 
763
    ; Get the address of the callers data
764
    mov     edi, [0x3010]
765
    add     edi, TASKDATA.mem_start
766
    add     edx, [edi]
767
    mov     esi, edx
768
 
769
    pop     eax
770
    push    eax
771
 
772
    push    ecx
773
    call    buildTCPPacket
774
    pop     ecx
775
 
776
    ; Check destination IP address.
777
    ; If it is the local host IP, route it back to IP_RX
778
 
779
    pop     ebx
780
    push    ecx
781
    mov     eax, NET1OUT_QUEUE
782
 
783
    mov     edx, [stack_ip]
784
    mov     ecx, [sktAddr ]
785
    mov     ecx, [ecx + 16]
786
    cmp     edx, ecx
787
    jne     swt_notlocal
788
    mov     eax, IPIN_QUEUE
789
 
790
swt_notlocal:
791
    pop     ecx
792
 
793
    push    ebx                 ; save ipbuffer number
794
 
795
    call    queue
796
 
797
    mov     esi, [sktAddr]
798
 
799
    ; increament SND.NXT in socket
800
    ; Amount to increment by is in ecx
801
    add     esi, 48
802
    call    add_inet_esi
803
 
804
    pop     ebx
805
 
806
    ; Copy the IP buffer to a resend queue
807
    ; If there isn't one, dont worry about it for now
808
    mov     esi, resendQ
809
    mov     ecx, 0
810
 
811
swt003:
812
    cmp     ecx, NUMRESENDENTRIES
813
    je      swt001              ; None found
814
    cmp     [esi], byte 0xFF
815
    je      swt002              ; found one
816
    inc     ecx
817
    add     esi, 4
818
    jmp     swt003
819
 
820
swt002:
821
    push    ebx
822
 
823
    ; OK, we have a buffer descriptor ptr in esi.
824
    ; resend entry # in ecx
825
    ;  Populate it
826
    ;  socket #
827
    ;  retries count
828
    ;  retry time
829
    ;  fill IP buffer associated with this descriptor
830
 
831
    mov     eax, [sktAddr]
832
    sub     eax, sockets
833
    shr     eax, 12             ; get skt #
834
    mov     [esi], al
835
    mov     [esi + 1], byte TCP_RETRIES
836
    mov     [esi + 2], word TCP_TIMEOUT
837
 
838
    inc     ecx
839
    ; Now get buffer location, and copy buffer across. argh! more copying,,
840
    mov     edi, resendBuffer - IPBUFFSIZE
841
swt002a:
842
    add     edi, IPBUFFSIZE
843
    loop    swt002a
844
 
845
    ; we have dest buffer location in edi
846
    pop     eax
847
    ; convert source buffer pointer eax to the absolute address
848
    mov     ecx, IPBUFFSIZE
849
    mul     ecx
850
    add     eax, IPbuffs
851
    mov     esi, eax
852
 
853
    ; do copy
854
    mov     ecx, IPBUFFSIZE
855
    cld
856
    rep     movsb
857
 
858
swt001:
859
    xor     eax, eax
860
 
861
swt_exit:
862
    ret
863