Subversion Repositories Kolibri OS

Rev

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