Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
425 victor 1
$Revision: 465 $
431 serge 2
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
3
;;                                                              ;;
4
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
5
;; Distributed under terms of the GNU General Public License    ;;
6
;;                                                              ;;
7
;;  SOCKET.INC                                                  ;;
8
;;                                                              ;;
9
;;  Sockets constants, structures and functions                 ;;
10
;;                                                              ;;
11
;;  Last revision: 11.11.2006                                   ;;
12
;;                                                              ;;
13
;;  This file contains the following:                           ;;
14
;;    is_localport_unused                                       ;;
15
;;    get_free_socket                                           ;;
16
;;    socket_open                                               ;;
17
;;    socket_open_tcp                                           ;;
18
;;    socket_close                                              ;;
19
;;    socket_close_tcp                                          ;;
20
;;    socket_poll                                               ;;
21
;;    socket_status                                             ;;
22
;;    socket_read                                               ;;
23
;;    socket_write                                              ;;
24
;;    socket_write_tcp                                          ;;
25
;;                                                              ;;
26
;;                                                              ;;
27
;;  Changes history:                                            ;;
28
;;   22.09.2003 - [Mike Hibbett] : mikeh@oceanfree.net          ;;
29
;;   11.11.2006 - [Johnny_B] and [smb]                          ;;
30
;;                                                              ;;
31
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
261 hidnplayr 32
 
33
;
34
;  Socket Descriptor + Buffer
35
;
36
;    0                   1                   2                   3
37
;    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
38
;
39
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
40
;  0|                    Status ( of this buffer )                  |
41
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
42
;  4|  Application Process ID                                       |
43
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
44
;  8|                  Local IP Address                             |
45
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
46
; 12| Local IP Port                 | Unused ( set to 0 )           |
47
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
48
; 16|                  Remote IP Address                            |
49
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
50
; 20| Remote IP Port                | Unused ( set to 0 )           |
51
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
52
; 24|   Rx Data Count                                   INTEL format|
53
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
54
; 28|                 TCB STATE                         INTEL format|
55
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
56
; 32|   TCB Timer (seconds)                             INTEL format|
57
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
58
; 36| ISS (Inital Sequence # used by this connection )   INET format|
59
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
60
; 40| IRS ( Inital Receive Sequence # )                  INET format|
61
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
62
; 44| SND.UNA  Seq # of unack'ed sent packets            INET format|
63
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
64
; 48| SND.NXT  Next send seq # to use                    INET format|
65
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
66
; 52| SND.WND  Send window                               INET format|
67
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
68
; 56| RCV.NXT  Next expected receive sequence #          INET format|
69
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
70
; 60| RCV.WND  Receive window                            INET format|
71
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
72
; 64| SEG.LEN  Segment length                           INTEL format|
73
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
74
; 68| SEG.WND  Segment window                           INTEL format|
75
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
76
; 72| Retransmit queue # NOW WINDOW SIZE TIMER          INTEL format|
77
;   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
379 serge 78
; 76|      RX offset from
261 hidnplayr 79
; 76|       RX Data                                                 |
80
;   +-+-+-..........                                               -+
81
 
82
 
83
; so, define struct
84
struc SOCKET
379 serge 85
{  .Status		    dd	 ?  ;+00 - Status ( of this buffer )
86
   .PID 		    dd	 ?  ;+04 - Application Process ID
323 hidnplayr 87
   .LocalIP		    dd	 ?  ;+08 -  Local IP Address
88
   .LocalPort		    dw	 ?  ;+12 - Local Port
89
   .UnusedL		    dw	 ?  ;+14 - may be removed in future
90
   .RemoteIP		    dd	 ?  ;+16 - Remote IP Address
91
   .RemotePort		    dw	 ?  ;+20 - Remote Port
92
   .UnusedR		    dw	 ?  ;+22 - may be removed in future
93
   .rxDataCount 	    dd	 ?  ;+24 - Rx Data Count
94
   .TCBState		    dd	 ?  ;+28 - TCB STATE
379 serge 95
   .TCBTimer		    dd	 ?  ;+32 - TCB Timer (seconds)
323 hidnplayr 96
   .ISS 		    dd	 ?  ;+36 - Initial Send Sequence
97
   .IRS 		    dd	 ?  ;+40 - Initial Receive Sequence
98
   .SND_UNA		    dd	 ?  ;+44 - Sequence number of unack'ed sent packets
379 serge 99
   .SND_NXT		    dd	 ?  ;+48 - Next send sequence number to use
323 hidnplayr 100
   .SND_WND		    dd	 ?  ;+52 - Send window
101
   .RCV_NXT		    dd	 ?  ;+56 - Next receive sequence number to use
102
   .RCV_WND		    dd	 ?  ;+60 - Receive window
103
   .SEG_LEN		    dd	 ?  ;+64 - Segment length
104
   .SEG_WND		    dd	 ?  ;+68 - Segment window
379 serge 105
   .wndsizeTimer	    dd	 ?  ;+72 - Retransmit queue # NOW WINDOW SIZE TIMER
323 hidnplayr 106
   .rxData		    dd	 ?  ;+76 - receive data buffer here
261 hidnplayr 107
}
108
 
109
virtual at 0
110
  SOCKET SOCKET
111
end virtual
112
 
379 serge 113
; simple macro calcing real memory address of SOCKET struct by socket's
261 hidnplayr 114
macro	Index2RealAddr reg
115
{
323 hidnplayr 116
	shl	reg, 12
379 serge 117
    add     reg, sockets
261 hidnplayr 118
}
119
 
120
;Constants
121
; current socket statuses
323 hidnplayr 122
SOCK_EMPTY	   equ	   0	    ; socket not in use
123
SOCK_OPEN	   equ	   1	    ; open issued, but no data sent
261 hidnplayr 124
 
125
; TCP opening modes
323 hidnplayr 126
SOCKET_PASSIVE	   equ	   0
127
SOCKET_ACTIVE	   equ	   1
261 hidnplayr 128
 
129
;***************************************************************************
130
;   Function
131
;      is_localport_unused
132
;
133
;   Description
134
;         scans through all the active sockets , looking to see if the
135
;      port number specified in bx is in use as a localport number.
136
;      This is useful when you want a to generate a unique local port
137
;      number.
138
;          On return, eax = 1 for free, 0 for in use
139
;
140
;***************************************************************************
141
is_localport_unused:
142
    mov     al, bh
143
    mov     ah, bl
144
    mov     bx, ax
145
 
146
    mov     edx, SOCKETBUFFSIZE * NUM_SOCKETS
147
    mov     ecx, NUM_SOCKETS
323 hidnplayr 148
    mov     eax, 0		      ; Assume the return value is 'in use'
261 hidnplayr 149
 
150
ilu1:
151
    sub     edx, SOCKETBUFFSIZE
152
    cmp     [edx + sockets + SOCKET.LocalPort], bx
323 hidnplayr 153
    loopnz  ilu1		  ; Return back if the socket is occupied
261 hidnplayr 154
 
323 hidnplayr 155
    jz	    ilu_exit
156
    inc     eax 			; return port not in use
261 hidnplayr 157
 
158
ilu_exit:
159
    ret
160
 
161
 
162
 
163
;***************************************************************************
164
;   Function
165
;      get_free_socket
166
;
167
;   Description
168
;
169
;***************************************************************************
170
get_free_socket:
171
    push    ecx
172
    mov     eax, SOCKETBUFFSIZE * NUM_SOCKETS
173
    mov     ecx, NUM_SOCKETS
174
 
175
gfs1:
176
    sub     eax, SOCKETBUFFSIZE
177
    cmp     [eax + sockets + SOCKET.Status], dword SOCK_EMPTY
323 hidnplayr 178
    loopnz  gfs1		  ; Return back if the socket is occupied
261 hidnplayr 179
    mov     eax, ecx
180
    pop     ecx
323 hidnplayr 181
    jz	    gfs_exit
261 hidnplayr 182
    mov     eax, 0xFFFFFFFF
183
 
184
gfs_exit:
185
    ret
186
 
187
 
188
;***************************************************************************
189
;   Function
190
;      socket_open
191
;
192
;   Description
193
;       find a free socket
194
;       local port in ebx
195
;       remote port in ecx
196
;       remote ip in edx
197
;       return socket # in eax, -1 if none available
198
;
199
;***************************************************************************
200
socket_open:
201
    call    get_free_socket
202
 
203
    cmp     eax, 0xFFFFFFFF
323 hidnplayr 204
    jz	    so_exit
261 hidnplayr 205
 
206
    ; ax holds the socket number that is free. Get real address
207
    push    eax
208
    Index2RealAddr eax
209
 
210
    mov     [eax + SOCKET.Status], dword SOCK_OPEN
211
 
323 hidnplayr 212
    xchg    bh, bl
213
    mov     [eax + SOCKET.LocalPort], bx
214
    xchg    ch, cl
215
    mov     [eax + SOCKET.RemotePort], cx
261 hidnplayr 216
 
217
    mov     ebx, [stack_ip]
379 serge 218
    mov     [eax + SOCKET.LocalIP], ebx
219
    mov     [eax + SOCKET.RemoteIP], edx
261 hidnplayr 220
    mov     [eax + SOCKET.rxDataCount], dword 0      ; recieved data count
221
 
379 serge 222
    mov     esi, [TASK_BASE]
261 hidnplayr 223
    mov     ebx, [esi+TASKDATA.pid]
323 hidnplayr 224
    mov     [eax + SOCKET.PID], ebx	    ; save the process ID
261 hidnplayr 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
323 hidnplayr 250
    jz	    so_exit
261 hidnplayr 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
 
323 hidnplayr 262
	xchg	bh, bl
379 serge 263
	mov	[eax + SOCKET.LocalPort], bx
261 hidnplayr 264
;    mov     [eax + 12], byte bh      ; Local port ( LS 16 bits )
265
;    mov     [eax + 13], byte bl      ; Local port ( LS 16 bits )
266
 
323 hidnplayr 267
	xchg	ch, cl
379 serge 268
	mov	[eax + SOCKET.RemotePort], cx
261 hidnplayr 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]
379 serge 273
    mov     [eax + SOCKET.LocalIP], ebx
274
    mov     [eax + SOCKET.RemoteIP], edx
275
    mov     [eax + SOCKET.rxDataCount], dword 0
261 hidnplayr 276
 
277
    ; Now fill in TCB state
278
    mov     ebx, TCB_LISTEN
279
    cmp     esi, SOCKET_PASSIVE
323 hidnplayr 280
    jz	    sot_001
261 hidnplayr 281
    mov     ebx, TCB_SYN_SENT
282
 
283
sot_001:
323 hidnplayr 284
    mov     [eax + SOCKET.TCBState], ebx	    ; Indicate the state of the TCB
261 hidnplayr 285
 
379 serge 286
    mov     esi, [TASK_BASE]
261 hidnplayr 287
    mov     ecx, [esi+TASKDATA.pid]
323 hidnplayr 288
    mov     [eax + SOCKET.PID], ecx	    ; save the process ID
261 hidnplayr 289
 
290
    cmp     ebx, TCB_LISTEN
323 hidnplayr 291
    je	    sot_done
261 hidnplayr 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
323 hidnplayr 297
    je	    sot_done
261 hidnplayr 298
 
299
    push    eax
300
 
323 hidnplayr 301
    mov     bl, 0x02	    ; SYN
261 hidnplayr 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
323 hidnplayr 345
    mov     eax, 0xFFFFFFFF	    ; assume this operation will fail..
261 hidnplayr 346
    cmp     [ebx + SOCKET.Status], dword SOCK_EMPTY
323 hidnplayr 347
    jz	    sc_exit
261 hidnplayr 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
323 hidnplayr 379
    je	    sct003		; None left
261 hidnplayr 380
    cmp     [esi], bl
323 hidnplayr 381
    je	    sct002		; found one
261 hidnplayr 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
323 hidnplayr 396
    mov     eax, 0xFFFFFFFF	    ; assume this operation will fail..
261 hidnplayr 397
    cmp     [ebx + SOCKET.Status], dword SOCK_EMPTY
323 hidnplayr 398
    jz	    sct_exit
261 hidnplayr 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
323 hidnplayr 404
    je	    stl_exit
261 hidnplayr 405
 
406
    push    eax
407
 
323 hidnplayr 408
    mov     bl, 0x11	    ; FIN + ACK
261 hidnplayr 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
323 hidnplayr 425
    je	    destroyTCB
261 hidnplayr 426
    cmp     eax, TCB_SYN_SENT
323 hidnplayr 427
    je	    destroyTCB
261 hidnplayr 428
    cmp     eax, TCB_SYN_RECEIVED
323 hidnplayr 429
    je	    sct_finwait1
261 hidnplayr 430
    cmp     eax, TCB_ESTABLISHED
323 hidnplayr 431
    je	    sct_finwait1
261 hidnplayr 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
323 hidnplayr 521
    mov     eax, [ebx + SOCKET.rxDataCount]	    ; get count of bytes
261 hidnplayr 522
    mov     ecx, 1
523
    test    eax, eax
323 hidnplayr 524
    jz	    sr2
261 hidnplayr 525
 
526
    dec     eax
323 hidnplayr 527
    mov     esi, ebx		; esi is address of socket
528
    mov     [ebx + SOCKET.rxDataCount], eax	    ; store new count
261 hidnplayr 529
    ;movzx   ebx, byte [ebx + SOCKET.rxData]  ; get the byte
323 hidnplayr 530
    movzx   ebx, byte [ebx + SOCKETHEADERSIZE]	; get the byte
261 hidnplayr 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
 
323 hidnplayr 550
;***************************************************************************
551
;   Function
552
;      socket_read_packet
553
;
554
;   Description
555
;       socket # in ebx
556
;       datapointer # in ecx
557
;       buffer size in edx
558
;       returns # of bytes copied in eax
559
;
560
;***************************************************************************
561
socket_read_packet:
562
    Index2RealAddr ebx					   ; get real socket address
563
    mov     eax, [ebx + SOCKET.rxDataCount]		   ; get count of bytes
564
    test    eax, eax					   ; if count of bytes is zero..
565
    jz	    .exit					   ; exit function (eax will be zero)
261 hidnplayr 566
 
323 hidnplayr 567
    test    edx, edx					   ; if buffer size is zero, copy all data
568
    jz	    .copyallbytes
569
    cmp     edx, eax					   ; if buffer size is larger then the bytes of data, copy all data
570
    jge     .copyallbytes
571
 
572
    sub     eax, edx					   ; store new count (data bytes in buffer - bytes we're about to copy)
573
    mov     [ebx + SOCKET.rxDataCount], eax		   ;
574
    push    eax
575
    mov     eax, edx					   ; number of bytes we want to copy must be in eax
576
    call    .startcopy					   ; copy to the application
577
 
578
    mov     esi, ebx					   ; now we're going to copy the remaining bytes to the beginning
579
    add     esi, SOCKETHEADERSIZE			   ; we dont need to copy the header
580
    mov     edi, esi					   ; edi is where we're going to copy to
581
    add     esi, edx					   ; esi is from where we copy
582
    pop     ecx 					   ; count of bytes we have left
583
    push    ecx 					   ; push it again so we can re-use it later
584
    shr     ecx, 2					   ; divide eax by 4
585
    cld
586
    rep     movsd					   ; copy all full dwords
587
    pop     ecx
588
    and     ecx, 3
589
    rep     movsb					   ; copy remaining bytes
590
 
591
    ret 						   ; at last, exit
592
 
593
.copyallbytes:
594
    xor     esi, esi
595
    mov     [ebx + SOCKET.rxDataCount], esi		   ; store new count (zero)
596
 
597
.startcopy:
598
    mov     edi, ecx					   ;
465 serge 599
 ;   add     edi, std_application_base_address              ; get data pointer to buffer in application
323 hidnplayr 600
 
601
    mov     esi, ebx					   ;
602
    add     esi, SOCKETHEADERSIZE			   ; we dont need to copy the header
603
    mov     ecx, eax					   ; eax is count of bytes
604
    push    ecx
605
    shr     ecx, 2					   ; divide eax by 4
606
    cld 						   ; copy all full dwords
607
    rep     movsd					   ;
608
    pop     ecx
609
    and     ecx, 3
610
    rep     movsb					   ; copy the rest bytes
611
 
612
.exit:
613
    ret 						   ; exit, or go back to shift remaining bytes if any
614
 
615
 
616
 
617
 
261 hidnplayr 618
;***************************************************************************
619
;   Function
620
;      socket_write
621
;
622
;   Description
623
;       socket in ebx
624
;       # of bytes to write in ecx
625
;       pointer to data in edx
626
;       returns 0 in eax ok, -1 == failed ( invalid socket, or
627
;       could not queue IP packet )
628
;
629
;***************************************************************************
630
socket_write:
631
    Index2RealAddr ebx
632
 
633
    mov     eax, 0xFFFFFFFF
634
    ; If the socket is invalid, return with an error code
635
    cmp     [ebx], dword SOCK_EMPTY
323 hidnplayr 636
    je	    sw_exit
261 hidnplayr 637
 
638
 
639
    mov     eax, EMPTY_QUEUE
640
    call    dequeue
641
    cmp     ax, NO_BUFFER
323 hidnplayr 642
    je	    sw_exit
261 hidnplayr 643
 
644
    ; Save the queue entry number
645
    push    eax
646
 
647
    ; save the pointers to the data buffer & size
648
    push    edx
649
    push    ecx
650
 
651
    ; convert buffer pointer eax to the absolute address
652
    mov     ecx, IPBUFFSIZE
653
    mul     ecx
654
    add     eax, IPbuffs
655
 
656
    mov     edx, eax
657
 
658
    ; So, ebx holds the socket ptr, edx holds the IPbuffer ptr
659
 
660
    ; Fill in the IP header ( some data is in the socket descriptor)
661
    mov     eax, [ebx + 8]
323 hidnplayr 662
    mov     [edx + 12], eax	 ; source IP
261 hidnplayr 663
    mov     eax, [ebx + 16]
323 hidnplayr 664
    mov     [edx + 16], eax	 ; Destination IP
261 hidnplayr 665
 
666
    mov     al, 0x45
323 hidnplayr 667
    mov     [edx], al	      ; Version, IHL
261 hidnplayr 668
    xor     al, al
669
    mov     [edx + 1], al     ; Type of service
670
 
323 hidnplayr 671
    pop     eax 		  ; Get the UDP data length
261 hidnplayr 672
    push    eax
673
 
323 hidnplayr 674
    add     eax, 20 + 8 	  ; add IP header and UDP header lengths
261 hidnplayr 675
    mov     [edx + 2], ah
676
    mov     [edx + 3], al
677
    xor     al, al
678
    mov     [edx + 4], al
679
    mov     [edx + 5], al
680
    mov     al, 0x40
681
    mov     [edx + 6], al
682
    xor     al, al
683
    mov     [edx + 7], al
684
    mov     al, 0x20
685
    mov     [edx + 8], al
686
    mov     al, 17
687
    mov     [edx + 9], al
688
 
689
    ; Checksum left unfilled
690
    xor     ax, ax
691
    mov     [edx + 10], ax
692
 
693
    ; Fill in the UDP header ( some data is in the socket descriptor)
694
    mov     ax, [ebx + 12]
695
    mov     [edx + 20], ax
696
 
697
    mov     ax, [ebx + 20]
698
    mov     [edx + 20 + 2], ax
699
 
700
    pop     eax
701
    push    eax
702
 
703
    add     eax, 8
704
    mov     [edx + 20 + 4], ah
705
    mov     [edx + 20 + 5], al
706
 
707
    ; Checksum left unfilled
708
    xor     ax, ax
709
    mov     [edx + 20 + 6], ax
710
 
323 hidnplayr 711
    pop     ecx 		 ; count of bytes to send
712
    mov     ebx, ecx		; need the length later
713
    pop     eax 		 ; get callers ptr to data to send
261 hidnplayr 714
 
715
    ; Get the address of the callers data
379 serge 716
    mov     edi, [TASK_BASE]
261 hidnplayr 717
    add     edi, TASKDATA.mem_start
718
    add     eax, [edi]
719
    mov     esi, eax
720
 
721
    mov     edi, edx
722
    add     edi, 28
723
    cld
323 hidnplayr 724
    rep     movsb		; copy the data across
261 hidnplayr 725
 
726
    ; we have edx as IPbuffer ptr.
727
    ; Fill in the UDP checksum
728
    ; First, fill in pseudoheader
729
    mov     eax, [edx + 12]
730
    mov     [pseudoHeader], eax
731
    mov     eax, [edx + 16]
732
    mov     [pseudoHeader+4], eax
323 hidnplayr 733
    mov     ax, 0x1100		  ; 0 + protocol
261 hidnplayr 734
    mov     [pseudoHeader+8], ax
735
    add     ebx, 8
736
    mov     eax, ebx
737
    mov     [pseudoHeader+10], ah
738
    mov     [pseudoHeader+11], al
739
 
740
    mov     eax, pseudoHeader
741
    mov     [checkAdd1], eax
742
    mov     [checkSize1], word 12
743
    mov     eax, edx
744
    add     eax, 20
745
    mov     [checkAdd2], eax
746
    mov     eax, ebx
323 hidnplayr 747
    mov     [checkSize2], ax	  ; was eax!! mjh 8/7/02
261 hidnplayr 748
 
749
    call    checksum
750
 
751
    ; store it in the UDP checksum ( in the correct order! )
752
    mov     ax, [checkResult]
753
 
754
    ; If the UDP checksum computes to 0, we must make it 0xffff
755
    ; (0 is reserved for 'not used')
756
    cmp     ax, 0
757
    jne     sw_001
758
    mov     ax, 0xffff
759
 
760
sw_001:
761
    mov     [edx + 20 + 6], ah
762
    mov     [edx + 20 + 7], al
763
 
764
    ; Fill in the IP header checksum
323 hidnplayr 765
    GET_IHL ecx,edx		 ; get IP-Header length
261 hidnplayr 766
    stdcall checksum_jb,edx,ecx  ; buf_ptr, buf_size
767
 
768
    mov     [edx + 10], ah
769
    mov     [edx + 11], al
770
 
771
    ; Check destination IP address.
772
    ; If it is the local host IP, route it back to IP_RX
773
 
774
    pop     ebx
775
    mov     eax, NET1OUT_QUEUE
776
 
777
    mov     ecx, [ edx + 16]
778
    mov     edx, [stack_ip]
779
    cmp     edx, ecx
780
    jne     sw_notlocal
781
    mov     eax, IPIN_QUEUE
782
 
783
sw_notlocal:
784
    ; Send it.
785
    call    queue
786
 
787
    xor     eax, eax
788
 
789
sw_exit:
790
    ret
791
 
792
 
793
 
794
;***************************************************************************
795
;   Function
796
;      socket_write_tcp
797
;
798
;   Description
799
;       socket in ebx
800
;       # of bytes to write in ecx
801
;       pointer to data in edx
802
;       returns 0 in eax ok, -1 == failed ( invalid socket, or
803
;       could not queue IP packet )
804
;
805
;***************************************************************************
806
socket_write_tcp:
807
	Index2RealAddr ebx
808
 
809
    mov     [sktAddr], ebx
810
 
811
    mov     eax, 0xFFFFFFFF
812
    ; If the socket is invalid, return with an error code
813
    cmp     [ebx], dword SOCK_EMPTY
323 hidnplayr 814
    je	    swt_exit
261 hidnplayr 815
 
816
    ; If the sockets window timer is nonzero, do not queue packet
817
    ; TODO - done
818
    cmp     [ebx + SOCKET.wndsizeTimer], dword 0
819
    jne     swt_exit
820
 
821
    mov     eax, EMPTY_QUEUE
822
    call    dequeue
823
    cmp     ax, NO_BUFFER
323 hidnplayr 824
    je	    swt_exit
261 hidnplayr 825
 
826
    push    eax
827
 
323 hidnplayr 828
    mov     bl, 0x10	    ; ACK
261 hidnplayr 829
 
830
    ; Get the address of the callers data
379 serge 831
    mov     edi, [TASK_BASE]
261 hidnplayr 832
    add     edi, TASKDATA.mem_start
833
    add     edx, [edi]
834
    mov     esi, edx
835
 
836
    pop     eax
837
    push    eax
838
 
839
    push    ecx
840
    call    buildTCPPacket
841
    pop     ecx
842
 
843
    ; Check destination IP address.
844
    ; If it is the local host IP, route it back to IP_RX
845
 
846
    pop     ebx
847
    push    ecx
848
    mov     eax, NET1OUT_QUEUE
849
 
850
    mov     edx, [stack_ip]
851
    mov     ecx, [sktAddr ]
852
    mov     ecx, [ecx + 16]
853
    cmp     edx, ecx
854
    jne     swt_notlocal
855
    mov     eax, IPIN_QUEUE
856
 
857
swt_notlocal:
858
    pop     ecx
859
 
323 hidnplayr 860
    push    ebx 		; save ipbuffer number
261 hidnplayr 861
 
862
    call    queue
863
 
864
    mov     esi, [sktAddr]
865
 
866
    ; increament SND.NXT in socket
867
    ; Amount to increment by is in ecx
868
    add     esi, 48
869
    call    add_inet_esi
870
 
871
    pop     ebx
872
 
873
    ; Copy the IP buffer to a resend queue
874
    ; If there isn't one, dont worry about it for now
875
    mov     esi, resendQ
876
    mov     ecx, 0
877
 
878
swt003:
879
    cmp     ecx, NUMRESENDENTRIES
323 hidnplayr 880
    je	    swt001		; None found
261 hidnplayr 881
    cmp     [esi], byte 0xFF
323 hidnplayr 882
    je	    swt002		; found one
261 hidnplayr 883
    inc     ecx
884
    add     esi, 4
885
    jmp     swt003
886
 
887
swt002:
888
    push    ebx
889
 
890
    ; OK, we have a buffer descriptor ptr in esi.
891
    ; resend entry # in ecx
892
    ;  Populate it
893
    ;  socket #
894
    ;  retries count
895
    ;  retry time
896
    ;  fill IP buffer associated with this descriptor
897
 
898
    mov     eax, [sktAddr]
899
    sub     eax, sockets
323 hidnplayr 900
    shr     eax, 12		; get skt #
261 hidnplayr 901
    mov     [esi], al
902
    mov     [esi + 1], byte TCP_RETRIES
903
    mov     [esi + 2], word TCP_TIMEOUT
904
 
905
    inc     ecx
906
    ; Now get buffer location, and copy buffer across. argh! more copying,,
907
    mov     edi, resendBuffer - IPBUFFSIZE
908
swt002a:
909
    add     edi, IPBUFFSIZE
910
    loop    swt002a
911
 
912
    ; we have dest buffer location in edi
913
    pop     eax
914
    ; convert source buffer pointer eax to the absolute address
915
    mov     ecx, IPBUFFSIZE
916
    mul     ecx
917
    add     eax, IPbuffs
918
    mov     esi, eax
919
 
920
    ; do copy
921
    mov     ecx, IPBUFFSIZE
922
    cld
923
    rep     movsb
924
 
925
swt001:
926
    xor     eax, eax
927
 
928
swt_exit:
929
    ret
930