Subversion Repositories Kolibri OS

Rev

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

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