Subversion Repositories Kolibri OS

Rev

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

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