Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
1159 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
2362 hidnplayr 3
;; Copyright (C) KolibriOS team 2004-2012. All rights reserved.    ;;
1159 hidnplayr 4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
2888 hidnplayr 6
;;  Part of the tcp/ip network stack for KolibriOS                 ;;
7
;;                                                                 ;;
8
;;   Written by hidnplayr@kolibrios.org,                           ;;
1529 hidnplayr 9
;;     and Clevermouse.                                            ;;
1159 hidnplayr 10
;;                                                                 ;;
1529 hidnplayr 11
;;       Based on code by mike.dld                                 ;;
1159 hidnplayr 12
;;                                                                 ;;
1529 hidnplayr 13
;;         GNU GENERAL PUBLIC LICENSE                              ;;
14
;;          Version 2, June 1991                                   ;;
15
;;                                                                 ;;
1159 hidnplayr 16
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
17
 
1206 hidnplayr 18
$Revision: 2924 $
1159 hidnplayr 19
 
1773 hidnplayr 20
 
2402 hidnplayr 21
struct  SOCKET
1249 hidnplayr 22
 
2402 hidnplayr 23
        NextPtr                 dd ? ; pointer to next socket in list
24
        PrevPtr                 dd ? ; pointer to previous socket in list
25
        Number                  dd ? ; socket number
1249 hidnplayr 26
 
2402 hidnplayr 27
        mutex                   MUTEX
1249 hidnplayr 28
 
2402 hidnplayr 29
        PID                     dd ? ; application process id
30
        Domain                  dd ? ; INET/UNIX/..
31
        Type                    dd ? ; RAW/STREAM/DGRAP
32
        Protocol                dd ? ; ICMP/IPv4/ARP/TCP/UDP
33
        errorcode               dd ?
2877 hidnplayr 34
        device                  dd ?
1249 hidnplayr 35
 
2402 hidnplayr 36
        options                 dd ?
37
        state                   dd ?
38
        backlog                 dw ? ; how many incomming connections that can be queued
1249 hidnplayr 39
 
2402 hidnplayr 40
        snd_proc                dd ?
41
        rcv_proc                dd ?
1536 hidnplayr 42
 
2305 hidnplayr 43
ends
1249 hidnplayr 44
 
2402 hidnplayr 45
struct  IP_SOCKET               SOCKET
1254 hidnplayr 46
 
2402 hidnplayr 47
        LocalIP                 rd 4
48
        RemoteIP                rd 4
1318 hidnplayr 49
 
2305 hidnplayr 50
ends
1159 hidnplayr 51
 
2402 hidnplayr 52
struct  TCP_SOCKET              IP_SOCKET
1249 hidnplayr 53
 
2402 hidnplayr 54
        LocalPort               dw ?
55
        RemotePort              dw ?
1514 hidnplayr 56
 
2402 hidnplayr 57
        t_state                 dd ? ; TCB state
58
        t_rxtshift              dd ?
59
        t_rxtcur                dd ?
60
        t_dupacks               dd ?
61
        t_maxseg                dd ?
62
        t_force                 dd ?
63
        t_flags                 dd ?
1514 hidnplayr 64
 
65
;---------------
66
; RFC783 page 21
67
 
68
; send sequence
2402 hidnplayr 69
        SND_UNA                 dd ? ; sequence number of unack'ed sent Packets
70
        SND_NXT                 dd ? ; next send sequence number to use
2890 hidnplayr 71
        SND_UP                  dd ? ; urgent pointer
2402 hidnplayr 72
        SND_WL1                 dd ? ; window minus one
73
        SND_WL2                 dd ? ;
74
        ISS                     dd ? ; initial send sequence number
75
        SND_WND                 dd ? ; send window
1514 hidnplayr 76
 
77
; receive sequence
2402 hidnplayr 78
        RCV_WND                 dw ? ; receive window
79
        RCV_NXT                 dd ? ; next receive sequence number to use
2890 hidnplayr 80
        RCV_UP                  dd ? ; urgent pointer
2402 hidnplayr 81
        IRS                     dd ? ; initial receive sequence number
1514 hidnplayr 82
 
83
;---------------------
84
; Additional variables
85
 
86
; receive variables
2402 hidnplayr 87
        RCV_ADV                 dd ?
1514 hidnplayr 88
 
89
; retransmit variables
2402 hidnplayr 90
        SND_MAX                 dd ?
1514 hidnplayr 91
 
92
; congestion control
2402 hidnplayr 93
        SND_CWND                dd ?
94
        SND_SSTHRESH            dd ?
1514 hidnplayr 95
 
96
;----------------------
97
; Transmit timing stuff
2402 hidnplayr 98
        t_idle                  dd ?
99
        t_rtt                   dd ?
100
        t_rtseq                 dd ?
101
        t_srtt                  dd ?
102
        t_rttvar                dd ?
103
        t_rttmin                dd ?
104
        max_sndwnd              dd ?
1514 hidnplayr 105
 
106
;-----------------
107
; Out-of-band data
2402 hidnplayr 108
        t_oobflags              dd ?
109
        t_iobc                  dd ?
110
        t_softerror             dd ?
1514 hidnplayr 111
 
112
 
113
;---------
2924 hidnplayr 114
; RFC 1323                              ; the order of next 4 elements may not change
1514 hidnplayr 115
 
2402 hidnplayr 116
        SND_SCALE               db ?
117
        RCV_SCALE               db ?
118
        requested_s_scale       db ?
119
        request_r_scale         db ?
1514 hidnplayr 120
 
2924 hidnplayr 121
        ts_recent               dd ?    ; a copy of the most-recent valid timestamp from the other end
2402 hidnplayr 122
        ts_recent_age           dd ?
123
        last_ack_sent           dd ?
1519 hidnplayr 124
 
2310 hidnplayr 125
 
1519 hidnplayr 126
;-------
127
; Timers
2402 hidnplayr 128
        timer_retransmission    dw ? ; rexmt
129
        timer_persist           dw ?
130
        timer_keepalive         dw ? ; keepalive/syn timeout
131
        timer_timed_wait        dw ? ; also used as 2msl timer
1519 hidnplayr 132
 
2890 hidnplayr 133
; extra
134
 
2891 hidnplayr 135
        sendalot                db ? ; also used as 'need output'
2924 hidnplayr 136
        ts_ecr                  dd ? ; timestamp echo reply
2890 hidnplayr 137
 
2305 hidnplayr 138
ends
1249 hidnplayr 139
 
2402 hidnplayr 140
struct  UDP_SOCKET              IP_SOCKET
1249 hidnplayr 141
 
2402 hidnplayr 142
        LocalPort               dw ?
143
        RemotePort              dw ?
144
        firstpacket             db ?
1249 hidnplayr 145
 
2305 hidnplayr 146
ends
1249 hidnplayr 147
 
148
 
2402 hidnplayr 149
struct  ICMP_SOCKET             IP_SOCKET
1249 hidnplayr 150
 
2402 hidnplayr 151
        Identifier              dw ?
1514 hidnplayr 152
 
2305 hidnplayr 153
ends
1514 hidnplayr 154
 
155
 
2402 hidnplayr 156
struct  RING_BUFFER
2311 hidnplayr 157
 
2402 hidnplayr 158
        start_ptr               dd ? ; Pointer to start of buffer
159
        end_ptr                 dd ? ; pointer to end of buffer
160
        read_ptr                dd ? ; Read pointer
161
        write_ptr               dd ? ; Write pointer
162
        size                    dd ? ; Number of bytes buffered
2311 hidnplayr 163
 
2305 hidnplayr 164
ends
1514 hidnplayr 165
 
2402 hidnplayr 166
struct  STREAM_SOCKET           TCP_SOCKET
1529 hidnplayr 167
 
2402 hidnplayr 168
        rcv                     RING_BUFFER
169
        snd                     RING_BUFFER
1529 hidnplayr 170
 
2305 hidnplayr 171
ends
1529 hidnplayr 172
 
2402 hidnplayr 173
struct  socket_queue_entry
1529 hidnplayr 174
 
2402 hidnplayr 175
        data_ptr                dd ?
176
        buf_ptr                 dd ?
177
        data_size               dd ?
1529 hidnplayr 178
 
1274 hidnplayr 179
ends
180
 
1514 hidnplayr 181
 
2614 hidnplayr 182
SOCKETBUFFSIZE          = 4096     ; in bytes
1514 hidnplayr 183
 
2614 hidnplayr 184
SOCKET_QUEUE_SIZE       = 10       ; maximum number ofincoming packets queued for 1 socket
1514 hidnplayr 185
; the incoming packet queue for sockets is placed in the socket struct itself, at this location from start
2614 hidnplayr 186
SOCKET_QUEUE_LOCATION   = (SOCKETBUFFSIZE - SOCKET_QUEUE_SIZE*sizeof.socket_queue_entry - sizeof.queue)
1249 hidnplayr 187
 
1159 hidnplayr 188
uglobal
2402 hidnplayr 189
        net_sockets     rd 4
190
        last_socket_num dd ?
191
        last_UDP_port   dw ? ; These values give the number of the last used ephemeral port
192
        last_TCP_port   dw ? ;
1159 hidnplayr 193
endg
194
 
195
 
1257 hidnplayr 196
;-----------------------------------------------------------------
1159 hidnplayr 197
;
198
; SOCKET_init
199
;
1257 hidnplayr 200
;-----------------------------------------------------------------
2402 hidnplayr 201
macro   SOCKET_init {
1159 hidnplayr 202
 
2402 hidnplayr 203
        xor     eax, eax
204
        mov     edi, net_sockets
205
        mov     ecx, 5
206
        rep     stosd
1159 hidnplayr 207
 
1529 hidnplayr 208
       @@:
2402 hidnplayr 209
        pseudo_random eax
210
        cmp     ax, MIN_EPHEMERAL_PORT
211
        jb      @r
212
        cmp     ax, MAX_EPHEMERAL_PORT
213
        ja      @r
214
        mov     [last_UDP_port], ax
1529 hidnplayr 215
 
216
       @@:
2402 hidnplayr 217
        pseudo_random eax
218
        cmp     ax, MIN_EPHEMERAL_PORT
219
        jb      @r
220
        cmp     ax, MAX_EPHEMERAL_PORT
221
        ja      @r
222
        mov     [last_TCP_port], ax
1529 hidnplayr 223
 
224
}
225
 
226
 
1257 hidnplayr 227
;-----------------------------------------------------------------
1159 hidnplayr 228
;
229
; Socket API (function 74)
230
;
1257 hidnplayr 231
;-----------------------------------------------------------------
2614 hidnplayr 232
align 4
233
sys_socket:
234
 
235
        cmp     ebx, 255
236
        jz      SOCKET_debug
237
 
238
        cmp     ebx, .number
239
        ja      s_error
240
        jmp     dword [.table + 4*ebx]
241
 
242
  .table:
2402 hidnplayr 243
        dd      SOCKET_open     ; 0
244
        dd      SOCKET_close    ; 1
245
        dd      SOCKET_bind     ; 2
246
        dd      SOCKET_listen   ; 3
247
        dd      SOCKET_connect  ; 4
248
        dd      SOCKET_accept   ; 5
249
        dd      SOCKET_send     ; 6
250
        dd      SOCKET_receive  ; 7
251
        dd      SOCKET_set_opt  ; 8
252
        dd      SOCKET_get_opt  ; 9
2614 hidnplayr 253
  .number = ($ - .table) / 4 - 1
2301 hidnplayr 254
 
1529 hidnplayr 255
s_error:
2402 hidnplayr 256
        DEBUGF  1,"socket error\n"
257
        mov     dword [esp+32], -1
1529 hidnplayr 258
 
2402 hidnplayr 259
        ret
1529 hidnplayr 260
 
1159 hidnplayr 261
 
2301 hidnplayr 262
 
1257 hidnplayr 263
;-----------------------------------------------------------------
1159 hidnplayr 264
;
265
; SOCKET_open
266
;
267
;  IN:  domain in ecx
268
;       type in edx
1196 hidnplayr 269
;       protocol in esi
1159 hidnplayr 270
;  OUT: eax is socket num, -1 on error
271
;
1257 hidnplayr 272
;-----------------------------------------------------------------
1206 hidnplayr 273
align 4
1514 hidnplayr 274
SOCKET_open:
1159 hidnplayr 275
 
2891 hidnplayr 276
        DEBUGF  1,"SOCKET_open: domain=%u type=%u protocol=%x\n", ecx, edx, esi
1159 hidnplayr 277
 
2402 hidnplayr 278
        push    ecx edx esi
279
        call    SOCKET_alloc
280
        pop     esi edx ecx
281
        jz      s_error
1159 hidnplayr 282
 
2402 hidnplayr 283
        mov     [esp+32], edi                   ; return socketnumber
1542 hidnplayr 284
 
2402 hidnplayr 285
        mov     [eax + SOCKET.Domain], ecx
286
        mov     [eax + SOCKET.Type], edx
287
        mov     [eax + SOCKET.Protocol], esi
1159 hidnplayr 288
 
2402 hidnplayr 289
        cmp     ecx, AF_INET4
290
        jne     .no_inet4
1529 hidnplayr 291
 
2402 hidnplayr 292
        cmp     edx, SOCK_DGRAM
293
        je      .udp
1536 hidnplayr 294
 
2402 hidnplayr 295
        cmp     edx, SOCK_STREAM
296
        je      .tcp
1529 hidnplayr 297
 
2402 hidnplayr 298
        cmp     edx, SOCK_RAW
299
        je      .raw
1541 hidnplayr 300
 
1536 hidnplayr 301
  .no_inet4:
2402 hidnplayr 302
        ret
1536 hidnplayr 303
 
1542 hidnplayr 304
align 4
305
  .raw:
2402 hidnplayr 306
        test    esi, esi       ; IP_PROTO_IP
307
        jz      .ip
1529 hidnplayr 308
 
2402 hidnplayr 309
        cmp     esi, IP_PROTO_ICMP
310
        je      .icmp
1529 hidnplayr 311
 
2402 hidnplayr 312
        cmp     esi, IP_PROTO_UDP
313
        je      .udp
1533 hidnplayr 314
 
2402 hidnplayr 315
        cmp     esi, IP_PROTO_TCP
316
        je      .tcp
1536 hidnplayr 317
 
2402 hidnplayr 318
        ret
1159 hidnplayr 319
 
1542 hidnplayr 320
align 4
1536 hidnplayr 321
  .udp:
2402 hidnplayr 322
        mov     [eax + SOCKET.Protocol], IP_PROTO_UDP
323
        mov     [eax + SOCKET.snd_proc], SOCKET_send_udp
324
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
325
        ret
1529 hidnplayr 326
 
1542 hidnplayr 327
align 4
328
  .tcp:
2402 hidnplayr 329
        mov     [eax + SOCKET.Protocol], IP_PROTO_TCP
330
        mov     [eax + SOCKET.snd_proc], SOCKET_send_tcp
331
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_tcp
1838 hidnplayr 332
 
2612 hidnplayr 333
        TCP_init_socket eax
2402 hidnplayr 334
        ret
1529 hidnplayr 335
 
336
 
1543 hidnplayr 337
align 4
338
  .ip:
2402 hidnplayr 339
        mov     [eax + SOCKET.snd_proc], SOCKET_send_ip
340
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
341
        ret
1541 hidnplayr 342
 
1542 hidnplayr 343
 
344
align 4
1541 hidnplayr 345
  .icmp:
2402 hidnplayr 346
        mov     [eax + SOCKET.snd_proc], SOCKET_send_icmp
347
        mov     [eax + SOCKET.rcv_proc], SOCKET_receive_dgram
348
        ret
1541 hidnplayr 349
 
350
 
351
 
1257 hidnplayr 352
;-----------------------------------------------------------------
1159 hidnplayr 353
;
354
; SOCKET_bind
355
;
356
;  IN:  socket number in ecx
357
;       pointer to sockaddr struct in edx
358
;       length of that struct in esi
359
;  OUT: 0 on success
360
;
1257 hidnplayr 361
;-----------------------------------------------------------------
1206 hidnplayr 362
align 4
1514 hidnplayr 363
SOCKET_bind:
1159 hidnplayr 364
 
2891 hidnplayr 365
        DEBUGF  1,"SOCKET_bind: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
1159 hidnplayr 366
 
2402 hidnplayr 367
        call    SOCKET_num_to_ptr
368
        jz      s_error
1159 hidnplayr 369
 
2402 hidnplayr 370
        cmp     esi, 2
371
        jb      s_error
1159 hidnplayr 372
 
2402 hidnplayr 373
        cmp     word [edx], AF_INET4
374
        je      .af_inet4
1159 hidnplayr 375
 
2402 hidnplayr 376
        cmp     word [edx], AF_UNIX
377
        je      .af_unix
1249 hidnplayr 378
 
2402 hidnplayr 379
        jmp     s_error
1249 hidnplayr 380
 
381
  .af_unix:
2402 hidnplayr 382
        ; TODO: write code here
1249 hidnplayr 383
 
2402 hidnplayr 384
        mov     dword [esp+32], 0
385
        ret
1249 hidnplayr 386
 
1159 hidnplayr 387
  .af_inet4:
388
 
2402 hidnplayr 389
        cmp     esi, 6
390
        jb      s_error
1159 hidnplayr 391
 
2622 hidnplayr 392
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
393
        je      .udp
1159 hidnplayr 394
 
2622 hidnplayr 395
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
396
        je      .tcp
1159 hidnplayr 397
 
2622 hidnplayr 398
        jmp     s_error
399
 
400
  .tcp:
401
  .udp:
402
 
403
        mov     ebx, [edx + 4]                  ; First, fill in the IP
404
        test    ebx, ebx                        ; If IP is 0, use default
405
        jnz     @f
406
        mov     ebx, [NET_DEFAULT]
407
        mov     ebx, [IP_LIST + 4*ebx]
408
       @@:
409
        mov     [eax + IP_SOCKET.LocalIP], ebx
410
 
411
        mov     bx, [edx + 2]                   ; Now fill in the port if it's still available
412
        call    SOCKET_check_port
413
        jz      s_error                         ; ZF is set by socket_check_port, on error
414
 
2891 hidnplayr 415
        DEBUGF  1,"SOCKET_bind: local ip=%u.%u.%u.%u\n",\
2402 hidnplayr 416
        [eax + IP_SOCKET.LocalIP + 0]:1,[eax + IP_SOCKET.LocalIP + 1]:1,\
417
        [eax + IP_SOCKET.LocalIP + 2]:1,[eax + IP_SOCKET.LocalIP + 3]:1
1159 hidnplayr 418
 
2402 hidnplayr 419
        mov     dword [esp+32], 0
420
        ret
1159 hidnplayr 421
 
422
 
423
 
424
 
1257 hidnplayr 425
;-----------------------------------------------------------------
1159 hidnplayr 426
;
427
; SOCKET_connect
428
;
429
;  IN:  socket number in ecx
430
;       pointer to sockaddr struct in edx
431
;       length of that struct in esi
432
;  OUT: 0 on success
433
;
1257 hidnplayr 434
;-----------------------------------------------------------------
1159 hidnplayr 435
align 4
1514 hidnplayr 436
SOCKET_connect:
1159 hidnplayr 437
 
2891 hidnplayr 438
        DEBUGF  1,"SOCKET_connect: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
1159 hidnplayr 439
 
2402 hidnplayr 440
        call    SOCKET_num_to_ptr
441
        jz      s_error
1159 hidnplayr 442
 
2402 hidnplayr 443
        cmp     esi, 8
444
        jb      s_error
1159 hidnplayr 445
 
2402 hidnplayr 446
        cmp     word [edx], AF_INET4
447
        je      .af_inet4
1159 hidnplayr 448
 
2402 hidnplayr 449
        jmp     s_error
1159 hidnplayr 450
 
451
  .af_inet4:
2402 hidnplayr 452
        cmp     [eax + IP_SOCKET.LocalIP], 0
453
        jne     @f
454
        push    [IP_LIST]
455
        pop     [eax + IP_SOCKET.LocalIP]
1543 hidnplayr 456
       @@:
1159 hidnplayr 457
 
2402 hidnplayr 458
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
459
        je      .udp
1159 hidnplayr 460
 
2402 hidnplayr 461
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
462
        je      .tcp
1159 hidnplayr 463
 
2402 hidnplayr 464
        cmp     [eax + SOCKET.Protocol], IP_PROTO_IP
465
        je      .ip
1541 hidnplayr 466
 
2402 hidnplayr 467
        cmp     [eax + SOCKET.Protocol], IP_PROTO_ICMP
468
        je      .ip
1542 hidnplayr 469
 
2402 hidnplayr 470
        jmp     s_error
1159 hidnplayr 471
 
1542 hidnplayr 472
align 4
1254 hidnplayr 473
  .udp:
2402 hidnplayr 474
        pusha
475
        lea     ecx, [eax + SOCKET.mutex]
476
        call    mutex_lock
477
        popa
1543 hidnplayr 478
 
2402 hidnplayr 479
        pushw   [edx + 2]
480
        pop     [eax + UDP_SOCKET.RemotePort]
1543 hidnplayr 481
 
2402 hidnplayr 482
        pushd   [edx + 4]
483
        pop     [eax + IP_SOCKET.RemoteIP]
1543 hidnplayr 484
 
2402 hidnplayr 485
        cmp     [eax + UDP_SOCKET.LocalPort], 0
486
        jne     @f
487
        call    SOCKET_find_port
1543 hidnplayr 488
       @@:
489
 
2402 hidnplayr 490
        mov     [eax + UDP_SOCKET.firstpacket], 0
1159 hidnplayr 491
 
2402 hidnplayr 492
        push    eax
493
        init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
494
        pop     eax
1159 hidnplayr 495
 
2402 hidnplayr 496
        lea     ecx, [eax + SOCKET.mutex]
497
        call    mutex_unlock
1159 hidnplayr 498
 
2402 hidnplayr 499
        mov     dword [esp+32], 0
500
        ret
501
 
1542 hidnplayr 502
align 4
1254 hidnplayr 503
  .tcp:
2402 hidnplayr 504
        pusha
505
        lea     ecx, [eax + SOCKET.mutex]
506
        call    mutex_lock
507
        popa
1159 hidnplayr 508
 
2402 hidnplayr 509
        pushw   [edx + 2]
510
        pop     [eax + TCP_SOCKET.RemotePort]
1159 hidnplayr 511
 
2402 hidnplayr 512
        pushd   [edx + 4]
513
        pop     [eax + IP_SOCKET.RemoteIP]
1159 hidnplayr 514
 
2402 hidnplayr 515
        cmp     [eax + TCP_SOCKET.LocalPort], 0
516
        jne     @f
517
        call    SOCKET_find_port
1543 hidnplayr 518
       @@:
1159 hidnplayr 519
 
2402 hidnplayr 520
        mov     [eax + TCP_SOCKET.timer_persist], 0
521
        mov     [eax + TCP_SOCKET.t_state], TCPS_SYN_SENT
2612 hidnplayr 522
 
2402 hidnplayr 523
        push    [TCP_sequence_num]
524
        add     [TCP_sequence_num], 6400
525
        pop     [eax + TCP_SOCKET.ISS]
526
        mov     [eax + TCP_SOCKET.timer_keepalive], TCP_time_keep_init
1519 hidnplayr 527
 
2612 hidnplayr 528
 
2402 hidnplayr 529
        TCP_sendseqinit eax
1529 hidnplayr 530
 
1543 hidnplayr 531
;        mov     [ebx + TCP_SOCKET.timer_retransmission],   ;; todo: create macro to set retransmission timer
1533 hidnplayr 532
 
2402 hidnplayr 533
        mov     ebx, eax
1159 hidnplayr 534
 
2402 hidnplayr 535
        lea     eax, [ebx + STREAM_SOCKET.snd]
536
        call    SOCKET_ring_create
1543 hidnplayr 537
 
2402 hidnplayr 538
        lea     eax, [ebx + STREAM_SOCKET.rcv]
539
        call    SOCKET_ring_create
1543 hidnplayr 540
 
2402 hidnplayr 541
        pusha
2403 hidnplayr 542
        lea     ecx, [eax + SOCKET.mutex]
2402 hidnplayr 543
        call    mutex_unlock
544
        popa
1733 hidnplayr 545
 
2402 hidnplayr 546
        mov     eax, ebx
547
        call    TCP_output
1733 hidnplayr 548
 
2402 hidnplayr 549
        mov     dword [esp+32], 0
550
        ret
1159 hidnplayr 551
 
1542 hidnplayr 552
align 4
553
  .ip:
2402 hidnplayr 554
        pusha
555
        lea     ecx, [eax + SOCKET.mutex]
556
        call    mutex_lock
557
        popa
1543 hidnplayr 558
 
2402 hidnplayr 559
        pushd   [edx + 4]
560
        pop     [eax + IP_SOCKET.RemoteIP]
1159 hidnplayr 561
 
2402 hidnplayr 562
        push    eax
563
        init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
564
        pop     eax
1543 hidnplayr 565
 
2402 hidnplayr 566
        lea     ecx, [eax + SOCKET.mutex]
567
        call    mutex_unlock
1541 hidnplayr 568
 
2402 hidnplayr 569
        mov     dword [esp+32], 0
570
        ret
1541 hidnplayr 571
 
2402 hidnplayr 572
 
1257 hidnplayr 573
;-----------------------------------------------------------------
1159 hidnplayr 574
;
575
; SOCKET_listen
576
;
577
;  IN:  socket number in ecx
578
;       backlog in edx
579
;  OUT: eax is socket num, -1 on error
580
;
1257 hidnplayr 581
;-----------------------------------------------------------------
1206 hidnplayr 582
align 4
1514 hidnplayr 583
SOCKET_listen:
1159 hidnplayr 584
 
2891 hidnplayr 585
        DEBUGF  1,"SOCKET_listen: socknum=%u backlog=%u\n", ecx, edx
1159 hidnplayr 586
 
2402 hidnplayr 587
        call    SOCKET_num_to_ptr
588
        jz      s_error
1159 hidnplayr 589
 
2402 hidnplayr 590
        cmp     [eax + SOCKET.Domain], AF_INET4
591
        jne     s_error
1254 hidnplayr 592
 
2402 hidnplayr 593
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
594
        jne     s_error
1254 hidnplayr 595
 
2402 hidnplayr 596
        cmp     [eax + TCP_SOCKET.LocalPort], 0
597
        je      s_error
1514 hidnplayr 598
 
2402 hidnplayr 599
        cmp     [eax + IP_SOCKET.LocalIP], 0
600
        jne     @f
601
        push    [IP_LIST]
602
        pop     [eax + IP_SOCKET.LocalIP]
1543 hidnplayr 603
       @@:
604
 
2402 hidnplayr 605
        cmp     edx, MAX_backlog
606
        jbe     @f
607
        mov     edx, MAX_backlog
1543 hidnplayr 608
       @@:
1159 hidnplayr 609
 
2402 hidnplayr 610
        mov     [eax + SOCKET.backlog], dx
611
        or      [eax + SOCKET.options], SO_ACCEPTCON
612
        mov     [eax + TCP_SOCKET.t_state], TCPS_LISTEN
2880 hidnplayr 613
        mov     [eax + TCP_SOCKET.timer_keepalive], 0           ; disable keepalive timer
1159 hidnplayr 614
 
2402 hidnplayr 615
        push    eax
616
        init_queue (eax + SOCKET_QUEUE_LOCATION)                ; Set up sockets queue
617
        pop     eax
1543 hidnplayr 618
 
2402 hidnplayr 619
        mov     dword [esp+32], 0
1514 hidnplayr 620
 
2402 hidnplayr 621
        ret
1159 hidnplayr 622
 
623
 
1257 hidnplayr 624
;-----------------------------------------------------------------
1159 hidnplayr 625
;
626
; SOCKET_accept
627
;
628
;  IN:  socket number in ecx
629
;       addr in edx
630
;       addrlen in esi
631
;  OUT: eax is socket num, -1 on error
632
;
1257 hidnplayr 633
;-----------------------------------------------------------------
1206 hidnplayr 634
align 4
1514 hidnplayr 635
SOCKET_accept:
1159 hidnplayr 636
 
2891 hidnplayr 637
        DEBUGF  1,"SOCKET_accept: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
1159 hidnplayr 638
 
2402 hidnplayr 639
        call    SOCKET_num_to_ptr
640
        jz      s_error
1159 hidnplayr 641
 
2402 hidnplayr 642
        test    [eax + SOCKET.options], SO_ACCEPTCON
643
        jz      s_error
1543 hidnplayr 644
 
2402 hidnplayr 645
        cmp     [eax + SOCKET.Domain], AF_INET4
646
        jne     s_error
1249 hidnplayr 647
 
2402 hidnplayr 648
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
649
        jne     s_error
1249 hidnplayr 650
 
2402 hidnplayr 651
        get_from_queue (eax + SOCKET_QUEUE_LOCATION), MAX_backlog, 4, s_error
2572 hidnplayr 652
        mov     eax, [esi]
1249 hidnplayr 653
 
2572 hidnplayr 654
; Change PID to that of the current process
655
        mov     ebx, [TASK_BASE]
656
        mov     ebx, [ebx + TASKDATA.pid]
657
        mov     [eax + SOCKET.PID], ebx
658
 
2402 hidnplayr 659
        call    SOCKET_ptr_to_num
660
        jz      s_error
661
        mov     [esp+32], eax
662
        ret
1514 hidnplayr 663
 
1159 hidnplayr 664
 
1257 hidnplayr 665
;-----------------------------------------------------------------
1159 hidnplayr 666
;
667
; SOCKET_close
668
;
669
;  IN:  socket number in ecx
670
;  OUT: eax is socket num, -1 on error
671
;
1257 hidnplayr 672
;-----------------------------------------------------------------
1206 hidnplayr 673
align 4
1514 hidnplayr 674
SOCKET_close:
1159 hidnplayr 675
 
2891 hidnplayr 676
        DEBUGF  1,"SOCKET_close: %u\n", ecx
1159 hidnplayr 677
 
2402 hidnplayr 678
        call    SOCKET_num_to_ptr
679
        jz      s_error
1159 hidnplayr 680
 
2402 hidnplayr 681
        cmp     [eax + SOCKET.Domain], AF_INET4
682
        jne     s_error
1159 hidnplayr 683
 
2402 hidnplayr 684
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
685
        je      .free
1159 hidnplayr 686
 
2402 hidnplayr 687
        cmp     [eax + SOCKET.Protocol], IP_PROTO_ICMP
688
        je      .free
1159 hidnplayr 689
 
2402 hidnplayr 690
        cmp     [eax + SOCKET.Protocol], IP_PROTO_IP
691
        je      .free
1542 hidnplayr 692
 
2402 hidnplayr 693
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
694
        je      .tcp
1159 hidnplayr 695
 
2402 hidnplayr 696
        jmp     s_error
1159 hidnplayr 697
 
698
  .tcp:
2402 hidnplayr 699
        cmp     [eax + TCP_SOCKET.t_state], TCPS_SYN_RECEIVED    ; state must be LISTEN, SYN_SENT or CLOSED
700
        jb      .free
1318 hidnplayr 701
 
2890 hidnplayr 702
        call    TCP_usrclosed
2891 hidnplayr 703
        call    TCP_output      ;;;; Fixme: is this nescessary??
2402 hidnplayr 704
        mov     dword [esp+32], 0
1159 hidnplayr 705
 
2402 hidnplayr 706
        ret
1159 hidnplayr 707
 
1514 hidnplayr 708
  .free:
2402 hidnplayr 709
        call    SOCKET_free
710
        mov     dword [esp+32], 0
1159 hidnplayr 711
 
2402 hidnplayr 712
        ret
1159 hidnplayr 713
 
714
 
1257 hidnplayr 715
;-----------------------------------------------------------------
1159 hidnplayr 716
;
717
; SOCKET_receive
718
;
719
;  IN:  socket number in ecx
1249 hidnplayr 720
;       addr to buffer in edx
721
;       length of buffer in esi
1159 hidnplayr 722
;       flags in edi
723
;  OUT: eax is number of bytes copied, -1 on error
724
;
1257 hidnplayr 725
;-----------------------------------------------------------------
1206 hidnplayr 726
align 4
1514 hidnplayr 727
SOCKET_receive:
1159 hidnplayr 728
 
2891 hidnplayr 729
        DEBUGF  1,"SOCKET_receive: socknum=%u bufaddr=%x buflength=%u flags=%x\n", ecx, edx, esi, edi
1514 hidnplayr 730
 
2402 hidnplayr 731
        call    SOCKET_num_to_ptr
732
        jz      s_error
1159 hidnplayr 733
 
2402 hidnplayr 734
        jmp     [eax + SOCKET.rcv_proc]
1533 hidnplayr 735
 
1536 hidnplayr 736
 
737
align 4
1541 hidnplayr 738
SOCKET_receive_dgram:
1536 hidnplayr 739
 
2402 hidnplayr 740
        DEBUGF  1,"SOCKET_receive: DGRAM\n"
1536 hidnplayr 741
 
2402 hidnplayr 742
        mov     ebx, esi
743
        mov     edi, edx                                        ; addr to buffer
1159 hidnplayr 744
 
2402 hidnplayr 745
        get_from_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, s_error       ; destroys esi and ecx
1536 hidnplayr 746
 
2402 hidnplayr 747
        mov     ecx, [esi + socket_queue_entry.data_size]
2891 hidnplayr 748
        DEBUGF  1,"SOCKET_receive: %u bytes data\n", ecx
1159 hidnplayr 749
 
2402 hidnplayr 750
        cmp     ecx, ebx
751
        ja      .too_small
1514 hidnplayr 752
 
2402 hidnplayr 753
        push    [esi + socket_queue_entry.buf_ptr]              ; save the buffer addr so we can clear it later
754
        mov     esi, [esi + socket_queue_entry.data_ptr]
2891 hidnplayr 755
        DEBUGF  1,"SOCKET_receive: Source buffer=%x real addr=%x\n", [esp], esi
2402 hidnplayr 756
        mov     [esp+32+4], ecx                                 ; return number of bytes copied
1159 hidnplayr 757
 
1514 hidnplayr 758
; copy the data
2402 hidnplayr 759
        shr     ecx, 1
760
        jnc     .nb
761
        movsb
1536 hidnplayr 762
  .nb:
2402 hidnplayr 763
        shr     ecx, 1
764
        jnc     .nw
765
        movsw
1536 hidnplayr 766
  .nw:
2402 hidnplayr 767
        test    ecx, ecx
768
        jz      .nd
769
        rep     movsd
1536 hidnplayr 770
  .nd:
1159 hidnplayr 771
 
2402 hidnplayr 772
        call    kernel_free                                     ; remove the packet
773
        ret
1514 hidnplayr 774
 
1536 hidnplayr 775
  .too_small:
1533 hidnplayr 776
 
2891 hidnplayr 777
        DEBUGF  1,"SOCKET_receive: Buffer too small\n"
2402 hidnplayr 778
        jmp     s_error
1536 hidnplayr 779
 
780
align 4
781
SOCKET_receive_tcp:
782
 
2402 hidnplayr 783
        DEBUGF  1,"SOCKET_receive: TCP\n"
1536 hidnplayr 784
 
2402 hidnplayr 785
        mov     ecx, esi
786
        mov     edi, edx
787
        add     eax, STREAM_SOCKET.rcv
2893 hidnplayr 788
        xor     edx, edx
2402 hidnplayr 789
        call    SOCKET_ring_read
790
        call    SOCKET_ring_free
1533 hidnplayr 791
 
2402 hidnplayr 792
        mov     [esp+32], ecx                                   ; return number of bytes copied
1533 hidnplayr 793
 
2402 hidnplayr 794
        ret
1159 hidnplayr 795
 
796
 
1257 hidnplayr 797
;-----------------------------------------------------------------
1159 hidnplayr 798
;
799
; SOCKET_send
800
;
801
;
802
;  IN:  socket number in ecx
1206 hidnplayr 803
;       pointer to data in edx
804
;       datalength in esi
1159 hidnplayr 805
;       flags in edi
806
;  OUT: -1 on error
807
;
1257 hidnplayr 808
;-----------------------------------------------------------------
1206 hidnplayr 809
align 4
1514 hidnplayr 810
SOCKET_send:
1159 hidnplayr 811
 
2891 hidnplayr 812
        DEBUGF  1,"SOCKET_send: socknum=%u data ptr=%x length=%u flags=%x\n", ecx, edx, esi, edi
1159 hidnplayr 813
 
2402 hidnplayr 814
        call    SOCKET_num_to_ptr
815
        jz      s_error
1159 hidnplayr 816
 
2402 hidnplayr 817
        mov     ecx, esi
818
        mov     esi, edx
1763 hidnplayr 819
 
2402 hidnplayr 820
        jmp     [eax + SOCKET.snd_proc]
1206 hidnplayr 821
 
822
 
1536 hidnplayr 823
align 4
824
SOCKET_send_udp:
1529 hidnplayr 825
 
2402 hidnplayr 826
        DEBUGF  1,"SOCKET_send: UDP\n"
1159 hidnplayr 827
 
2573 hidnplayr 828
        mov     [esp+32], ecx
2402 hidnplayr 829
        call    UDP_output
2573 hidnplayr 830
        cmp     eax, -1
831
        je      s_error
2402 hidnplayr 832
        ret
1159 hidnplayr 833
 
834
 
1536 hidnplayr 835
align 4
836
SOCKET_send_tcp:
1254 hidnplayr 837
 
2402 hidnplayr 838
        DEBUGF  1,"SOCKET_send: TCP\n"
1254 hidnplayr 839
 
2402 hidnplayr 840
        push    eax
841
        add     eax, STREAM_SOCKET.snd
842
        call    SOCKET_ring_write
843
        pop     eax
1536 hidnplayr 844
 
2621 hidnplayr 845
        mov     [esp+32], ecx
846
 
2402 hidnplayr 847
        call    TCP_output
848
        ret
1159 hidnplayr 849
 
1249 hidnplayr 850
 
1543 hidnplayr 851
align 4
852
SOCKET_send_ip:
1249 hidnplayr 853
 
2891 hidnplayr 854
        DEBUGF  1,"SOCKET_send: IPv4\n"
1543 hidnplayr 855
 
2573 hidnplayr 856
        mov     [esp+32], ecx
2402 hidnplayr 857
        call    IPv4_output_raw
2573 hidnplayr 858
        cmp     eax, -1
859
        je      s_error
2402 hidnplayr 860
        ret
1543 hidnplayr 861
 
2573 hidnplayr 862
 
1541 hidnplayr 863
align 4
864
SOCKET_send_icmp:
1249 hidnplayr 865
 
2402 hidnplayr 866
        DEBUGF  1,"SOCKET_send: ICMP\n"
1541 hidnplayr 867
 
2573 hidnplayr 868
        mov     [esp+32], ecx
2402 hidnplayr 869
        call    ICMP_output_raw
2573 hidnplayr 870
        cmp     eax, -1
871
        je      s_error
2402 hidnplayr 872
        ret
1541 hidnplayr 873
 
874
 
875
 
876
 
1257 hidnplayr 877
;-----------------------------------------------------------------
1256 clevermous 878
;
1257 hidnplayr 879
; SOCKET_get_options
1256 clevermous 880
;
1514 hidnplayr 881
;  IN:  ecx = socket number
882
;       edx = pointer to the options:
1257 hidnplayr 883
;               dd      level, optname, optval, optlen
1256 clevermous 884
;  OUT: -1 on error
885
;
886
; At moment, uses only pseudo-optname -2 for get last_ack_number for TCP.
887
; TODO: find best way to notify that send()'ed data were acknowledged
1831 hidnplayr 888
; Also pseudo-optname -3 is valid and returns socket state, one of TCPS_*.
1256 clevermous 889
;
1257 hidnplayr 890
;-----------------------------------------------------------------
891
align 4
1514 hidnplayr 892
SOCKET_get_opt:
1257 hidnplayr 893
 
2402 hidnplayr 894
        DEBUGF  1,"SOCKET_get_opt\n"
1514 hidnplayr 895
 
2402 hidnplayr 896
        call    SOCKET_num_to_ptr
897
        jz      s_error
1514 hidnplayr 898
 
2402 hidnplayr 899
        cmp     dword [edx], IP_PROTO_TCP
900
        jne     s_error
901
        cmp     dword [edx+4], -2
902
        je      @f
903
        cmp     dword [edx+4], -3
904
        jne     s_error
1299 clevermous 905
@@:
1514 hidnplayr 906
;        mov     eax, [edx+12]
907
;        test    eax, eax
908
;        jz      .fail
909
;        cmp     dword [eax], 4
910
;        mov     dword [eax], 4
911
;        jb      .fail
912
;        stdcall net_socket_num_to_addr, ecx
913
;        test    eax, eax
914
;        jz      .fail
915
;        ; todo: check that eax is really TCP socket
916
;        mov     ecx, [eax + TCP_SOCKET.last_ack_number]
917
;        cmp     dword [edx+4], -2
918
;        jz      @f
919
;        mov     ecx, [eax + TCP_SOCKET.state]
1299 clevermous 920
@@:
2402 hidnplayr 921
        mov     eax, [edx+8]
922
        test    eax, eax
923
        jz      @f
924
        mov     [eax], ecx
1256 clevermous 925
@@:
2402 hidnplayr 926
        mov     dword [esp+32], 0
927
        ret
1159 hidnplayr 928
 
929
 
1529 hidnplayr 930
 
2731 hidnplayr 931
;-----------------------------------------------------------------
932
;
933
; SOCKET_set_options
934
;
935
;  IN:  ecx = socket number
936
;       edx = pointer to the options:
2877 hidnplayr 937
;               dd      level, optname, optlen, optval
2731 hidnplayr 938
;  OUT: -1 on error
939
;
940
;-----------------------------------------------------------------
1542 hidnplayr 941
align 4
942
SOCKET_set_opt:
943
 
2731 hidnplayr 944
        DEBUGF  1,"SOCKET_set_opt\n"
945
 
946
        call    SOCKET_num_to_ptr
947
        jz      s_error
948
 
2877 hidnplayr 949
        cmp     dword [edx], SOL_SOCKET
950
        jne     s_error
2731 hidnplayr 951
 
2877 hidnplayr 952
        cmp     dword [edx+4], SO_BINDTODEVICE
953
        je      .bind
2731 hidnplayr 954
 
2877 hidnplayr 955
        jmp     s_error
956
 
957
  .bind:
958
        cmp     dword [edx+8], 0
959
        je      .unbind
960
 
961
        movzx   edx, byte [edx + 9]
962
        cmp     edx, MAX_NET_DEVICES
963
        ja      s_error
964
 
965
        mov     edx, [NET_DRV_LIST + 4*edx]
966
        test    edx, edx
967
        jz      s_error
968
        mov     [eax + SOCKET.device], edx
969
 
2891 hidnplayr 970
        DEBUGF  1,"SOCKET_set_opt: Bound socket %x to device %x\n",eax, edx
2877 hidnplayr 971
 
972
        mov     dword [esp+32], 0       ; success!
2402 hidnplayr 973
        ret
1542 hidnplayr 974
 
2877 hidnplayr 975
  .unbind:
976
        mov     [eax + SOCKET.device], 0
1542 hidnplayr 977
 
2877 hidnplayr 978
        mov     dword [esp+32], 0       ; success!
979
        ret
1542 hidnplayr 980
 
2877 hidnplayr 981
 
982
 
1257 hidnplayr 983
;-----------------------------------------------------------------
1206 hidnplayr 984
;
1529 hidnplayr 985
; SOCKET_debug
986
;
987
;  Copies socket variables to application buffer
988
;
989
;  IN:  ecx = socket number
990
;       edx = pointer to buffer
991
;
992
;  OUT: -1 on error
993
;-----------------------------------------------------------------
994
align 4
995
SOCKET_debug:
996
 
2891 hidnplayr 997
        DEBUGF  1,"SOCKET_debug\n"
1529 hidnplayr 998
 
2402 hidnplayr 999
        call    SOCKET_num_to_ptr
1000
        jz      s_error
1529 hidnplayr 1001
 
2402 hidnplayr 1002
        mov     esi, eax
1003
        mov     edi, edx
1004
        mov     ecx, SOCKETBUFFSIZE/4
1005
        rep     movsd
1529 hidnplayr 1006
 
2402 hidnplayr 1007
        mov     dword [esp+32], 0
1008
        ret
1529 hidnplayr 1009
 
1010
 
1011
;-----------------------------------------------------------------
1012
;
1514 hidnplayr 1013
; SOCKET_find_port
1206 hidnplayr 1014
;
1514 hidnplayr 1015
; Fills in the local port number for TCP and UDP sockets
1016
; This procedure always works because the number of sockets is
1017
; limited to a smaller number then the number of possible ports
1206 hidnplayr 1018
;
1514 hidnplayr 1019
;  IN:  eax = socket pointer
1020
;  OUT: /
1206 hidnplayr 1021
;
1257 hidnplayr 1022
;-----------------------------------------------------------------
1206 hidnplayr 1023
align 4
1514 hidnplayr 1024
SOCKET_find_port:
1159 hidnplayr 1025
 
2402 hidnplayr 1026
        DEBUGF  1,"SOCKET_find_port\n"
1159 hidnplayr 1027
 
2402 hidnplayr 1028
        push    ebx esi ecx
1514 hidnplayr 1029
 
2402 hidnplayr 1030
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
1031
        je      .udp
1159 hidnplayr 1032
 
2402 hidnplayr 1033
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
1034
        je      .tcp
1159 hidnplayr 1035
 
2402 hidnplayr 1036
        jmp     .error
1514 hidnplayr 1037
 
1038
  .done:
2402 hidnplayr 1039
        mov     [eax + UDP_SOCKET.LocalPort], bx
1514 hidnplayr 1040
  .error:
2402 hidnplayr 1041
        pop     ecx esi ebx
1042
        ret
1514 hidnplayr 1043
 
1206 hidnplayr 1044
  .udp:
2402 hidnplayr 1045
        mov     bx, [last_UDP_port]
1046
        call    .findit
1047
        mov     [last_UDP_port], bx
1048
        jmp     .done
1206 hidnplayr 1049
 
1050
  .tcp:
2402 hidnplayr 1051
        mov     bx, [last_TCP_port]
1052
        call    .findit
1053
        mov     [last_TCP_port], bx
1054
        jmp     .done
1206 hidnplayr 1055
 
1056
 
1514 hidnplayr 1057
  .restart:
2402 hidnplayr 1058
        mov     bx, MIN_EPHEMERAL_PORT
1514 hidnplayr 1059
  .findit:
2402 hidnplayr 1060
        inc     bx
1206 hidnplayr 1061
 
2402 hidnplayr 1062
        cmp     bx, MAX_EPHEMERAL_PORT
1063
        jz      .restart
1206 hidnplayr 1064
 
2402 hidnplayr 1065
        call    SOCKET_check_port
1066
        jz      .findit
1206 hidnplayr 1067
 
2402 hidnplayr 1068
        ret
1206 hidnplayr 1069
 
1257 hidnplayr 1070
 
1071
 
1072
;-----------------------------------------------------------------
1206 hidnplayr 1073
;
1542 hidnplayr 1074
; SOCKET_check_port (to be used with AF_INET only!)
1206 hidnplayr 1075
;
1514 hidnplayr 1076
; Checks if a local port number is unused
1077
; If the proposed port number is unused, it is filled in in the socket structure
1206 hidnplayr 1078
;
1514 hidnplayr 1079
;  IN:  eax = socket ptr (to find out if its a TCP/UDP socket)
1080
;        bx = proposed socket number
1206 hidnplayr 1081
;
1514 hidnplayr 1082
;  OUT:  ZF = cleared on error
1083
;
1257 hidnplayr 1084
;-----------------------------------------------------------------
1206 hidnplayr 1085
align 4
1514 hidnplayr 1086
SOCKET_check_port:
1087
 
2891 hidnplayr 1088
        DEBUGF  1,"SOCKET_check_port: "
1514 hidnplayr 1089
 
2402 hidnplayr 1090
        mov     ecx, [eax + SOCKET.Protocol]
2622 hidnplayr 1091
        mov     edx, [eax + IP_SOCKET.LocalIP]
2402 hidnplayr 1092
        mov     esi, net_sockets
1206 hidnplayr 1093
 
1094
  .next_socket:
2402 hidnplayr 1095
        mov     esi, [esi + SOCKET.NextPtr]
1096
        or      esi, esi
1097
        jz      .port_ok
1206 hidnplayr 1098
 
2402 hidnplayr 1099
        cmp     [esi + SOCKET.Protocol], ecx
1100
        jne     .next_socket
1206 hidnplayr 1101
 
2622 hidnplayr 1102
        cmp     [esi + IP_SOCKET.LocalIP], edx
1103
        jne     .next_socket
1104
 
2402 hidnplayr 1105
        cmp     [esi + UDP_SOCKET.LocalPort], bx
1106
        jne     .next_socket
1206 hidnplayr 1107
 
2402 hidnplayr 1108
        DEBUGF  1,"local port %u already in use\n", bx
1109
        ret
1206 hidnplayr 1110
 
1111
  .port_ok:
2891 hidnplayr 1112
        DEBUGF  1,"local port %u is free\n", bx
2402 hidnplayr 1113
        mov     [eax + UDP_SOCKET.LocalPort], bx
1114
        or      bx, bx                                  ; set the zero-flag
1514 hidnplayr 1115
 
2402 hidnplayr 1116
        ret
1206 hidnplayr 1117
 
1118
 
1257 hidnplayr 1119
 
1120
;-----------------------------------------------------------------
1206 hidnplayr 1121
;
1514 hidnplayr 1122
; SOCKET_input
1206 hidnplayr 1123
;
1536 hidnplayr 1124
; Updates a (stateless) socket with received data
1206 hidnplayr 1125
;
1514 hidnplayr 1126
; Note: the mutex should already be set !
1206 hidnplayr 1127
;
1249 hidnplayr 1128
;  IN:  eax = socket ptr
1514 hidnplayr 1129
;       ebx = pointer to device struct
1130
;       ecx = data size
1131
;       esi = ptr to data
1132
;       [esp] = ptr to buf
1133
;       [esp + 4] = buf size
1249 hidnplayr 1134
;
1514 hidnplayr 1135
;  OUT: /
1206 hidnplayr 1136
;
1257 hidnplayr 1137
;-----------------------------------------------------------------
1206 hidnplayr 1138
align 4
1514 hidnplayr 1139
SOCKET_input:
1206 hidnplayr 1140
 
2402 hidnplayr 1141
        DEBUGF  1,"SOCKET_input: socket=%x, data=%x size=%u\n", eax, esi, ecx
1206 hidnplayr 1142
 
2402 hidnplayr 1143
        mov     [esp+4], ecx
1144
        push    esi
1145
        mov     esi, esp
1514 hidnplayr 1146
 
2402 hidnplayr 1147
        add_to_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, SOCKET_input.full
1514 hidnplayr 1148
 
2402 hidnplayr 1149
        DEBUGF  1,"SOCKET_input: queued packet successfully\n"
1150
        add     esp, sizeof.socket_queue_entry
1206 hidnplayr 1151
 
2402 hidnplayr 1152
        pusha
1153
        lea     ecx, [eax + SOCKET.mutex]
1154
        call    mutex_unlock
1155
        popa
1156
 
1157
        jmp     SOCKET_notify_owner
1158
 
1514 hidnplayr 1159
  .full:
2402 hidnplayr 1160
        DEBUGF  2,"SOCKET_input: socket %x is full!\n", eax
1206 hidnplayr 1161
 
2402 hidnplayr 1162
        pusha
1163
        lea     ecx, [eax + SOCKET.mutex]
1164
        call    mutex_unlock
1165
        popa
1514 hidnplayr 1166
 
2402 hidnplayr 1167
        call    kernel_free
1168
        add     esp, 8
1533 hidnplayr 1169
 
2402 hidnplayr 1170
        ret
1171
 
1172
 
1533 hidnplayr 1173
;--------------------------
1174
;
1175
; eax = ptr to ring struct (just a buffer of the right size)
1176
;
1177
align 4
1178
SOCKET_ring_create:
1179
 
2402 hidnplayr 1180
        push    esi
1181
        mov     esi, eax
1543 hidnplayr 1182
 
2402 hidnplayr 1183
        push    edx
1184
        stdcall create_ring_buffer, SOCKET_MAXDATA, PG_SW
1185
        pop     edx
1533 hidnplayr 1186
 
2402 hidnplayr 1187
        DEBUGF  1,"SOCKET_ring_created: %x\n", eax
1188
        mov     [esi + RING_BUFFER.start_ptr], eax
1189
        mov     [esi + RING_BUFFER.write_ptr], eax
1190
        mov     [esi + RING_BUFFER.read_ptr], eax
1191
        mov     [esi + RING_BUFFER.size], 0
2888 hidnplayr 1192
        add     eax, SOCKET_MAXDATA
2402 hidnplayr 1193
        mov     [esi + RING_BUFFER.end_ptr], eax
1194
        mov     eax, esi
1195
        pop     esi
1533 hidnplayr 1196
 
2402 hidnplayr 1197
        ret
1533 hidnplayr 1198
 
1514 hidnplayr 1199
;-----------------------------------------------------------------
1200
;
1533 hidnplayr 1201
; SOCKET_ring_write
1529 hidnplayr 1202
;
1533 hidnplayr 1203
; Adds data to a stream socket, and updates write pointer and size
1529 hidnplayr 1204
;
1205
;  IN:  eax = ptr to ring struct
1206
;       ecx = data size
1207
;       esi = ptr to data
1208
;
1533 hidnplayr 1209
;  OUT: ecx = number of bytes stored
1529 hidnplayr 1210
;
1211
;-----------------------------------------------------------------
1212
align 4
1533 hidnplayr 1213
SOCKET_ring_write:
1529 hidnplayr 1214
 
2402 hidnplayr 1215
        DEBUGF  1,"SOCKET_ring_write: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx
1529 hidnplayr 1216
 
2402 hidnplayr 1217
        add     [eax + RING_BUFFER.size], ecx
2573 hidnplayr 1218
        jc      .way_too_large
2402 hidnplayr 1219
        cmp     [eax + RING_BUFFER.size], SOCKET_MAXDATA
1220
        ja      .too_large
1529 hidnplayr 1221
 
1222
  .copy:
2402 hidnplayr 1223
        mov     edi, [eax + RING_BUFFER.write_ptr]
1224
        DEBUGF  2,"SOCKET_ring_write: %u bytes from %x to %x\n", ecx, esi, edi
1529 hidnplayr 1225
 
2402 hidnplayr 1226
        push    ecx
1227
        shr     ecx, 1
1228
        jnc     .nb
1229
        movsb
1536 hidnplayr 1230
  .nb:
2402 hidnplayr 1231
        shr     ecx, 1
1232
        jnc     .nw
1233
        movsw
1536 hidnplayr 1234
  .nw:
2402 hidnplayr 1235
        test    ecx, ecx
1236
        jz      .nd
1237
        rep     movsd
1536 hidnplayr 1238
  .nd:
2402 hidnplayr 1239
        pop     ecx
1529 hidnplayr 1240
 
2402 hidnplayr 1241
        cmp     edi, [eax + RING_BUFFER.end_ptr]
1242
        jae     .wrap
1243
        mov     [eax + RING_BUFFER.write_ptr], edi
1533 hidnplayr 1244
 
2402 hidnplayr 1245
        ret
1529 hidnplayr 1246
 
1533 hidnplayr 1247
  .wrap:
2402 hidnplayr 1248
        sub     edi, SOCKET_MAXDATA
1249
        mov     [eax + RING_BUFFER.write_ptr], edi
1533 hidnplayr 1250
 
2402 hidnplayr 1251
        ret
1533 hidnplayr 1252
 
2404 hidnplayr 1253
  .too_large:                                                           ; update size, we will fill buffer completely
1254
        sub     [eax + RING_BUFFER.size], SOCKET_MAXDATA
2402 hidnplayr 1255
        sub     ecx, [eax + RING_BUFFER.size]
2404 hidnplayr 1256
        mov     [eax + RING_BUFFER.size], SOCKET_MAXDATA
2573 hidnplayr 1257
        ja      .copy
1529 hidnplayr 1258
 
2573 hidnplayr 1259
  .full:
2402 hidnplayr 1260
        DEBUGF  2,"SOCKET_ring_write: ring buffer is full!\n"
1261
        xor     ecx, ecx
1262
        ret
1529 hidnplayr 1263
 
2573 hidnplayr 1264
  .way_too_large:
1265
        sub     [eax + RING_BUFFER.size], ecx
1266
        mov     ecx, SOCKET_MAXDATA
1267
        sub     ecx, [eax + RING_BUFFER.size]
1268
        ja      .copy
1269
        jmp     .full
1529 hidnplayr 1270
 
2573 hidnplayr 1271
 
1272
 
1529 hidnplayr 1273
;-----------------------------------------------------------------
1274
;
1275
; SOCKET_ring_read
1276
;
2893 hidnplayr 1277
;  IN:  eax = ring struct ptr
1278
;       ecx = bytes to read
1279
;       edx = offset
1529 hidnplayr 1280
;       edi = ptr to buffer
1281
;
2893 hidnplayr 1282
;  OUT: ecx = number of bytes read (0 on error)
1529 hidnplayr 1283
;
1284
;-----------------------------------------------------------------
1285
align 4
1286
SOCKET_ring_read:
1287
 
2893 hidnplayr 1288
        DEBUGF  1,"SOCKET_ring_read: ringbuff=%x ptr=%x size=%u offset=%x\n", eax, edi, ecx, edx
1529 hidnplayr 1289
 
2893 hidnplayr 1290
        mov     esi, [eax + RING_BUFFER.read_ptr]
1291
        add     esi, edx                                        ; esi = start_ptr + offset
1292
 
1293
        neg     edx
1294
        add     edx, [eax + RING_BUFFER.size]                   ; edx = snd.size - offset
1295
        jle     .no_data_at_all
1296
 
1297
        cmp     ecx, edx
2402 hidnplayr 1298
        ja      .less_data
1529 hidnplayr 1299
 
1300
  .copy:
2402 hidnplayr 1301
        DEBUGF  2,"SOCKET_ring_read: %u bytes from %x to %x\n", ecx, esi, edi
1302
        push    ecx
1303
        shr     ecx, 1
1304
        jnc     .nb
1305
        movsb
1536 hidnplayr 1306
  .nb:
2402 hidnplayr 1307
        shr     ecx, 1
1308
        jnc     .nw
1309
        movsw
1536 hidnplayr 1310
  .nw:
2402 hidnplayr 1311
        test    ecx, ecx
1312
        jz      .nd
1313
        rep     movsd
1536 hidnplayr 1314
  .nd:
2402 hidnplayr 1315
        pop     ecx
2893 hidnplayr 1316
        ret
1529 hidnplayr 1317
 
1830 hidnplayr 1318
  .no_data_at_all:
2894 hidnplayr 1319
        DEBUGF  1,"SOCKET_ring_read: no data at all!\n"
2402 hidnplayr 1320
        ret
1529 hidnplayr 1321
 
1533 hidnplayr 1322
  .less_data:
2893 hidnplayr 1323
        mov     ecx, edx
2402 hidnplayr 1324
        jmp     .copy
1529 hidnplayr 1325
 
1326
 
1327
;-----------------------------------------------------------------
1328
;
1329
; SOCKET_ring_free
1330
;
1331
; Free's some bytes from the ringbuffer
1332
;
1333
;  IN:  eax = ptr to ring struct
1334
;       ecx = data size
1335
;
1336
;  OUT: ecx = number of bytes free-ed
1337
;
1338
;-----------------------------------------------------------------
1339
align 4
1340
SOCKET_ring_free:
1341
 
2402 hidnplayr 1342
        DEBUGF  1,"SOCKET_ring_free: %u bytes from ring %x\n", ecx, eax
1529 hidnplayr 1343
 
2402 hidnplayr 1344
        sub     [eax + RING_BUFFER.size], ecx
2888 hidnplayr 1345
        jb      .error
2402 hidnplayr 1346
        add     [eax + RING_BUFFER.read_ptr], ecx
1529 hidnplayr 1347
 
2402 hidnplayr 1348
        mov     edx, [eax + RING_BUFFER.end_ptr]
1349
        cmp     [eax + RING_BUFFER.read_ptr], edx
1350
        jb      @f
1351
        sub     [eax + RING_BUFFER.read_ptr], SOCKET_MAXDATA
1529 hidnplayr 1352
       @@:
2402 hidnplayr 1353
        ret
1529 hidnplayr 1354
 
2888 hidnplayr 1355
  .error:       ; we could free all available bytes, but that would be stupid, i guess..
1356
        DEBUGF  1,"SOCKET_ring_free: buffer=%x error!\n", eax
2402 hidnplayr 1357
        add     [eax + RING_BUFFER.size], ecx
1358
        xor     ecx, ecx
1359
        ret
1529 hidnplayr 1360
 
1361
 
1362
;-----------------------------------------------------------------
1363
;
1514 hidnplayr 1364
; SOCKET_notify_owner
1365
;
1366
; notify's the owner of a socket that something happened
1367
;
1368
;  IN:  eax = socket ptr
1369
;  OUT: /
1370
;
1371
;-----------------------------------------------------------------
1372
align 4
1373
SOCKET_notify_owner:
1374
 
2402 hidnplayr 1375
        DEBUGF  1,"SOCKET_notify_owner: %x\n", eax
1514 hidnplayr 1376
 
2402 hidnplayr 1377
        call    SOCKET_check
1378
        jz      .error
1514 hidnplayr 1379
 
2402 hidnplayr 1380
        push    eax ecx esi
1514 hidnplayr 1381
 
1382
; socket exists, now try to flag an event to the application
1383
 
2402 hidnplayr 1384
        mov     eax, [eax + SOCKET.PID]
2629 hidnplayr 1385
        test    eax, eax
1386
        jz      .error2
2402 hidnplayr 1387
        mov     ecx, 1
1388
        mov     esi, TASK_DATA + TASKDATA.pid
1206 hidnplayr 1389
 
1390
       .next_pid:
2402 hidnplayr 1391
        cmp     [esi], eax
1392
        je      .found_pid
1393
        inc     ecx
1394
        add     esi, 0x20
1395
        cmp     ecx, [TASK_COUNT]
1396
        jbe     .next_pid
1206 hidnplayr 1397
 
1514 hidnplayr 1398
; PID not found, TODO: close socket!
1399
 
2402 hidnplayr 1400
        jmp     .error2
1514 hidnplayr 1401
 
1206 hidnplayr 1402
       .found_pid:
2402 hidnplayr 1403
        shl     ecx, 8
1404
        or      [ecx + SLOT_BASE + APPDATA.event_mask], EVENT_NETWORK
1405
        mov     [check_idle_semaphore], 200
1206 hidnplayr 1406
 
2402 hidnplayr 1407
        DEBUGF  1,"SOCKET_notify_owner: succes!\n"
1514 hidnplayr 1408
 
1409
  .error2:
2402 hidnplayr 1410
        pop     esi ecx eax
1536 hidnplayr 1411
 
1514 hidnplayr 1412
  .error:
1413
 
2402 hidnplayr 1414
        ret
1206 hidnplayr 1415
 
1416
 
1514 hidnplayr 1417
;--------------------------------------------------------------------
1418
;
1419
; SOCKET_alloc
1420
;
1159 hidnplayr 1421
; Allocate memory for socket data and put new socket into the list
1422
; Newly created socket is initialized with calling PID and number and
1423
; put into beginning of list (which is a fastest way).
1424
;
1514 hidnplayr 1425
; IN:  /
1426
; OUT: eax = 0 on error, socket ptr otherwise
1427
;      edi = socket number
1428
;       ZF = cleared on error
1159 hidnplayr 1429
;
1514 hidnplayr 1430
;--------------------------------------------------------------------
1431
align 4
1432
SOCKET_alloc:
1433
 
2402 hidnplayr 1434
        push    ebx
1514 hidnplayr 1435
 
2402 hidnplayr 1436
        stdcall kernel_alloc, SOCKETBUFFSIZE
1437
        DEBUGF  1, "SOCKET_alloc: ptr=%x\n", eax
1438
        or      eax, eax
1439
        jz      .exit
1159 hidnplayr 1440
 
1514 hidnplayr 1441
; zero-initialize allocated memory
2402 hidnplayr 1442
        push    eax
1443
        mov     edi, eax
1444
        mov     ecx, SOCKETBUFFSIZE / 4
1445
        xor     eax, eax
1446
        rep     stosd
1447
        pop     eax
1159 hidnplayr 1448
 
1536 hidnplayr 1449
; set send-and receive procedures to return -1
2402 hidnplayr 1450
        mov     [eax + SOCKET.snd_proc], s_error
1451
        mov     [eax + SOCKET.rcv_proc], s_error
1536 hidnplayr 1452
 
1514 hidnplayr 1453
; find first free socket number and use it
2402 hidnplayr 1454
        mov     edi, [last_socket_num]
1159 hidnplayr 1455
  .next_socket_number:
2402 hidnplayr 1456
        inc     edi
1457
        jz      .next_socket_number     ; avoid socket nr 0
1458
        cmp     edi, -1
1459
        je      .next_socket_number     ; avoid socket nr -1
1460
        mov     ebx, net_sockets
1159 hidnplayr 1461
  .next_socket:
2402 hidnplayr 1462
        mov     ebx, [ebx + SOCKET.NextPtr]
1463
        test    ebx, ebx
1464
        jz      .last_socket
1536 hidnplayr 1465
 
2402 hidnplayr 1466
        cmp     [ebx + SOCKET.Number], edi
1467
        jne     .next_socket
1468
        jmp     .next_socket_number
1159 hidnplayr 1469
 
1514 hidnplayr 1470
  .last_socket:
2402 hidnplayr 1471
        mov     [last_socket_num], edi
1472
        mov     [eax + SOCKET.Number], edi
1473
        DEBUGF  1, "SOCKET_alloc: number=%u\n", edi
1159 hidnplayr 1474
 
1514 hidnplayr 1475
; Fill in PID
2402 hidnplayr 1476
        mov     ebx, [TASK_BASE]
1477
        mov     ebx, [ebx + TASKDATA.pid]
1478
        mov     [eax + SOCKET.PID], ebx
1514 hidnplayr 1479
 
2403 hidnplayr 1480
; init mutex
1481
        pusha
1482
        lea     ecx, [eax + SOCKET.mutex]
1483
        call    mutex_init
1484
        popa
1485
 
1529 hidnplayr 1486
; add socket to the list by re-arranging some pointers
2402 hidnplayr 1487
        mov     ebx, [net_sockets + SOCKET.NextPtr]
1514 hidnplayr 1488
 
2402 hidnplayr 1489
        mov     [eax + SOCKET.PrevPtr], net_sockets
1490
        mov     [eax + SOCKET.NextPtr], ebx
1514 hidnplayr 1491
 
2402 hidnplayr 1492
        test    ebx, ebx
1493
        jz      @f
1494
 
1495
        pusha
1496
        lea     ecx, [ebx + SOCKET.mutex]
1497
        call    mutex_lock
1498
        popa
1499
 
1500
        mov     [ebx + SOCKET.PrevPtr], eax
1501
 
1502
        pusha
1503
        lea     ecx, [ebx + SOCKET.mutex]
1504
        call    mutex_unlock
1505
        popa
1514 hidnplayr 1506
       @@:
1507
 
2402 hidnplayr 1508
        mov     [net_sockets + SOCKET.NextPtr], eax
1509
        or      eax, eax                ; used to clear zero flag
1159 hidnplayr 1510
  .exit:
2402 hidnplayr 1511
        pop     ebx
1514 hidnplayr 1512
 
2402 hidnplayr 1513
        ret
1159 hidnplayr 1514
 
1514 hidnplayr 1515
 
1516
;----------------------------------------------------
1159 hidnplayr 1517
;
1514 hidnplayr 1518
; SOCKET_free
1159 hidnplayr 1519
;
1514 hidnplayr 1520
; Free socket data memory and remove socket from the list
1521
;
1522
; IN:  eax = socket ptr
1523
; OUT: /
1524
;
1525
;----------------------------------------------------
1526
align 4
1527
SOCKET_free:
1159 hidnplayr 1528
 
2402 hidnplayr 1529
        DEBUGF  1, "SOCKET_free: %x\n", eax
1514 hidnplayr 1530
 
2402 hidnplayr 1531
        call    SOCKET_check
1532
        jz      .error
1159 hidnplayr 1533
 
2402 hidnplayr 1534
        push    ebx
1514 hidnplayr 1535
 
2402 hidnplayr 1536
        pusha
1537
        lea     ecx, [eax + SOCKET.mutex]
1538
        call    mutex_lock
1539
        popa
1514 hidnplayr 1540
 
2402 hidnplayr 1541
        cmp     [eax + SOCKET.Domain], AF_INET4
1542
        jnz     .no_tcp
1529 hidnplayr 1543
 
2402 hidnplayr 1544
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
1545
        jnz     .no_tcp
1546
 
1547
        mov     ebx, eax
1548
        stdcall kernel_free, [ebx + STREAM_SOCKET.rcv.start_ptr]
1549
        stdcall kernel_free, [ebx + STREAM_SOCKET.snd.start_ptr]
1550
        mov     eax, ebx
1536 hidnplayr 1551
  .no_tcp:
1529 hidnplayr 1552
 
2402 hidnplayr 1553
        push    eax                             ; this will be passed to kernel_free
1554
        mov     ebx, [eax + SOCKET.NextPtr]
1555
        mov     eax, [eax + SOCKET.PrevPtr]
1514 hidnplayr 1556
 
2402 hidnplayr 1557
        DEBUGF  1, "SOCKET_free: linking socket %x to socket %x\n", eax, ebx
1514 hidnplayr 1558
 
2402 hidnplayr 1559
        test    eax, eax
1560
        jz      @f
1561
        mov     [eax + SOCKET.NextPtr], ebx
1514 hidnplayr 1562
       @@:
1159 hidnplayr 1563
 
2402 hidnplayr 1564
        test    ebx, ebx
1565
        jz      @f
1566
        mov     [ebx + SOCKET.PrevPtr], eax
1514 hidnplayr 1567
       @@:
1249 hidnplayr 1568
 
2402 hidnplayr 1569
        call    kernel_free
1570
        pop     ebx
1159 hidnplayr 1571
 
2402 hidnplayr 1572
        DEBUGF  1, "SOCKET_free: success!\n"
1514 hidnplayr 1573
 
1159 hidnplayr 1574
  .error:
2402 hidnplayr 1575
        ret
1159 hidnplayr 1576
 
1543 hidnplayr 1577
;------------------------------------
1578
;
1579
; SOCKET_fork
1580
;
1581
; Create a child socket
1582
;
1533 hidnplayr 1583
; IN:  socket nr in ebx
1543 hidnplayr 1584
; OUT: child socket nr in eax
1585
;
1586
;-----------------------------------
1529 hidnplayr 1587
align 4
1588
SOCKET_fork:
1589
 
2402 hidnplayr 1590
        DEBUGF  1,"SOCKET_fork: %x\n", ebx
1529 hidnplayr 1591
 
1543 hidnplayr 1592
; Exit if backlog queue is full
2402 hidnplayr 1593
        mov     eax, [ebx + SOCKET_QUEUE_LOCATION + queue.size]
1594
        cmp     ax, [ebx + SOCKET.backlog]
1595
        jae     .fail
1543 hidnplayr 1596
 
1529 hidnplayr 1597
; Allocate new socket
2402 hidnplayr 1598
        push    ebx
1599
        call    SOCKET_alloc
1600
        pop     ebx
1601
        jz      .fail
1529 hidnplayr 1602
 
2402 hidnplayr 1603
        push    eax
1604
        mov     esi, esp
1605
        add_to_queue (ebx + SOCKET_QUEUE_LOCATION), MAX_backlog, 4, .fail2
1606
        pop     eax
1543 hidnplayr 1607
 
1608
; Copy structure from current socket to new
1609
; We start at PID to preserve the socket num, and the 2 pointers at beginning of socket
2402 hidnplayr 1610
        lea     esi, [ebx + SOCKET.PID]
1611
        lea     edi, [eax + SOCKET.PID]
1612
        mov     ecx, (SOCKET_QUEUE_LOCATION - SOCKET.PID + 3)/4
1613
        rep     movsd
1529 hidnplayr 1614
 
2402 hidnplayr 1615
        and     [eax + SOCKET.options], not SO_ACCEPTCON
1529 hidnplayr 1616
 
2402 hidnplayr 1617
        ret
1529 hidnplayr 1618
 
1543 hidnplayr 1619
  .fail2:
2402 hidnplayr 1620
        add     esp, 4+4+4
1543 hidnplayr 1621
  .fail:
2402 hidnplayr 1622
        DEBUGF  1,"SOCKET_fork: failed\n"
1623
        xor     eax, eax
1624
        ret
1529 hidnplayr 1625
 
1543 hidnplayr 1626
 
1514 hidnplayr 1627
;---------------------------------------------------
1628
;
1629
; SOCKET_num_to_ptr
1630
;
1159 hidnplayr 1631
; Get socket structure address by its number
1632
;
1514 hidnplayr 1633
; IN:  ecx = socket number
1533 hidnplayr 1634
; OUT: eax = 0 on error, socket ptr otherwise
1514 hidnplayr 1635
;       ZF = set on error
1159 hidnplayr 1636
;
1514 hidnplayr 1637
;---------------------------------------------------
1638
align 4
1639
SOCKET_num_to_ptr:
1159 hidnplayr 1640
 
2891 hidnplayr 1641
        DEBUGF  1,"SOCKET_num_to_ptr: num=%u ", ecx
1514 hidnplayr 1642
 
2402 hidnplayr 1643
        mov     eax, net_sockets
1514 hidnplayr 1644
 
1159 hidnplayr 1645
  .next_socket:
2402 hidnplayr 1646
        mov     eax, [eax + SOCKET.NextPtr]
1647
        or      eax, eax
1648
        jz      .error
1649
        cmp     [eax + SOCKET.Number], ecx
1650
        jne     .next_socket
1159 hidnplayr 1651
 
2402 hidnplayr 1652
        test    eax, eax
1159 hidnplayr 1653
 
2891 hidnplayr 1654
        DEBUGF  1,"ptr=%x\n", eax
1655
        ret
1656
 
1159 hidnplayr 1657
  .error:
2891 hidnplayr 1658
        DEBUGF  1,"not found\n", eax
2402 hidnplayr 1659
        ret
1159 hidnplayr 1660
 
1514 hidnplayr 1661
 
1662
;---------------------------------------------------
1159 hidnplayr 1663
;
1514 hidnplayr 1664
; SOCKET_ptr_to_num
1159 hidnplayr 1665
;
1514 hidnplayr 1666
; Get socket number by its address
1667
;
1668
; IN:  eax = socket ptr
1669
; OUT: eax = 0 on error, socket num otherwise
1670
;       ZF = set on error
1671
;
1672
;---------------------------------------------------
1673
align 4
1674
SOCKET_ptr_to_num:
1675
 
2891 hidnplayr 1676
        DEBUGF  1,"SOCKET_ptr_to_num: ptr=%x ", eax
1514 hidnplayr 1677
 
2402 hidnplayr 1678
        call    SOCKET_check
1679
        jz      .error
1159 hidnplayr 1680
 
2402 hidnplayr 1681
        mov     eax, [eax + SOCKET.Number]
1514 hidnplayr 1682
 
2891 hidnplayr 1683
        DEBUGF  1,"num=%u\n", eax
1684
        ret
1514 hidnplayr 1685
 
1686
  .error:
2891 hidnplayr 1687
        DEBUGF  1,"not found\n", eax
2402 hidnplayr 1688
        ret
1514 hidnplayr 1689
 
1690
 
1691
;---------------------------------------------------
1692
;
1693
; SOCKET_check
1694
;
1695
; checks if the given value is really a socket ptr
1696
;
1697
; IN:  eax = socket ptr
1698
; OUT: eax = 0 on error, unchanged otherwise
1699
;       ZF = set on error
1700
;
1701
;---------------------------------------------------
1702
align 4
1703
SOCKET_check:
1704
 
2402 hidnplayr 1705
        DEBUGF  1,"SOCKET_check: %x\n", eax
1514 hidnplayr 1706
 
2402 hidnplayr 1707
        push    ebx
1708
        mov     ebx, net_sockets
1514 hidnplayr 1709
 
1159 hidnplayr 1710
  .next_socket:
2402 hidnplayr 1711
        mov     ebx, [ebx + SOCKET.NextPtr]
1712
        or      ebx, ebx
1713
        jz      .done
1714
        cmp     ebx, eax
1715
        jnz     .next_socket
1159 hidnplayr 1716
 
1514 hidnplayr 1717
  .done:
2402 hidnplayr 1718
        mov     eax, ebx
1719
        test    eax, eax
1720
        pop     ebx
1514 hidnplayr 1721
 
2402 hidnplayr 1722
        ret
1159 hidnplayr 1723
 
1514 hidnplayr 1724
 
1725
 
1726
;---------------------------------------------------
1727
;
1728
; SOCKET_check_owner
1729
;
1730
; checks if the caller application owns the socket
1731
;
1732
; IN:  eax = socket ptr
1733
; OUT:  ZF = true/false
1734
;
1735
;---------------------------------------------------
1736
align 4
1737
SOCKET_check_owner:
1738
 
2402 hidnplayr 1739
        DEBUGF  1,"SOCKET_check_owner: %x\n", eax
1514 hidnplayr 1740
 
2402 hidnplayr 1741
        push    ebx
1742
        mov     ebx, [TASK_BASE]
1743
        mov     ebx, [ecx + TASKDATA.pid]
1744
        cmp     [eax + SOCKET.PID], ebx
1745
        pop      ebx
1514 hidnplayr 1746
 
2402 hidnplayr 1747
        ret
1514 hidnplayr 1748
 
1749
 
1750
 
1751
 
1885 hidnplayr 1752
;------------------------------------------------------
1514 hidnplayr 1753
;
1754
; SOCKET_process_end
1755
;
1756
; Kernel calls this function when a certain process ends
1757
; This function will check if the process had any open sockets
1758
; And update them accordingly
1759
;
2867 hidnplayr 1760
; IN:  edx = pid
1514 hidnplayr 1761
; OUT: /
1762
;
1763
;------------------------------------------------------
1764
align 4
1765
SOCKET_process_end:
1766
 
2867 hidnplayr 1767
        DEBUGF  1,"SOCKET_process_end: %x\n", edx
1514 hidnplayr 1768
 
2402 hidnplayr 1769
        push    ebx
1770
        mov     ebx, net_sockets
1514 hidnplayr 1771
 
1772
  .next_socket:
2402 hidnplayr 1773
        mov     ebx, [ebx + SOCKET.NextPtr]
1514 hidnplayr 1774
  .test_socket:
2402 hidnplayr 1775
        test    ebx, ebx
1776
        jz      .done
1514 hidnplayr 1777
 
2867 hidnplayr 1778
        cmp     [ebx + SOCKET.PID], edx
2402 hidnplayr 1779
        jne     .next_socket
1514 hidnplayr 1780
 
2891 hidnplayr 1781
        DEBUGF  1,"SOCKET_process_end: killing socket %x\n", ebx
1514 hidnplayr 1782
 
2402 hidnplayr 1783
        mov     [ebx + SOCKET.PID], 0
1514 hidnplayr 1784
 
2402 hidnplayr 1785
        cmp     [ebx + SOCKET.Protocol], IP_PROTO_TCP
1786
        je      .tcp
1514 hidnplayr 1787
 
2629 hidnplayr 1788
; The socket is stateless, just kill it right away!
1514 hidnplayr 1789
 
2402 hidnplayr 1790
        mov     eax, ebx
1791
        mov     ebx, [ebx + SOCKET.NextPtr]
1792
        call    SOCKET_free
1793
        jmp     .test_socket
1514 hidnplayr 1794
 
1795
  .tcp:
2629 hidnplayr 1796
        push    [ebx + SOCKET.NextPtr]
1797
        mov     eax, ebx
2869 hidnplayr 1798
        call    TCP_disconnect
2629 hidnplayr 1799
        pop     ebx
1800
        jmp     .test_socket
1885 hidnplayr 1801
 
1514 hidnplayr 1802
  .done:
2402 hidnplayr 1803
        pop     ebx
1514 hidnplayr 1804
 
2402 hidnplayr 1805
        ret
1773 hidnplayr 1806
 
1807
 
1808
 
1809
 
1885 hidnplayr 1810
;-----------------------------------------------------------------
1811
;
1812
; SOCKET_is_connecting
1813
;
1814
;  IN:  eax = socket ptr
1815
;  OUT: /
1816
;
1817
;-----------------------------------------------------------------
1773 hidnplayr 1818
 
1885 hidnplayr 1819
align 4
1820
SOCKET_is_connecting:
1773 hidnplayr 1821
 
2891 hidnplayr 1822
        DEBUGF  1,"SOCKET_is_connecting: %x\n", eax
1773 hidnplayr 1823
 
2402 hidnplayr 1824
        and     [eax + SOCKET.options], not (SS_ISCONNECTED + SS_ISDISCONNECTING + SS_ISCONFIRMING)
1825
        or      [eax + SOCKET.options], SS_ISCONNECTING
1773 hidnplayr 1826
 
2402 hidnplayr 1827
        jmp     SOCKET_notify_owner
1885 hidnplayr 1828
 
1829
 
1830
 
1773 hidnplayr 1831
;-----------------------------------------------------------------
1832
;
1885 hidnplayr 1833
; SOCKET_is_connected
1834
;
1835
;  IN:  eax = socket ptr
1836
;  OUT: /
1837
;
1838
;-----------------------------------------------------------------
1839
 
1840
align 4
1841
SOCKET_is_connected:
1842
 
2891 hidnplayr 1843
        DEBUGF  1,"SOCKET_is_connected: %x\n", eax
1885 hidnplayr 1844
 
2402 hidnplayr 1845
        and     [eax + SOCKET.options], not (SS_ISCONNECTING + SS_ISDISCONNECTING + SS_ISCONFIRMING)
1846
        or      [eax + SOCKET.options], SS_ISCONNECTED
1885 hidnplayr 1847
 
2402 hidnplayr 1848
        jmp     SOCKET_notify_owner
1885 hidnplayr 1849
 
1850
 
1851
 
1852
 
1853
;-----------------------------------------------------------------
1854
;
1773 hidnplayr 1855
; SOCKET_is_disconnecting
1856
;
1857
;  IN:  eax = socket ptr
1858
;  OUT: /
1859
;
1860
;-----------------------------------------------------------------
1861
 
1862
align 4
1863
SOCKET_is_disconnecting:
1864
 
2891 hidnplayr 1865
        DEBUGF  1,"SOCKET_is_disconnecting: %x\n", eax
1866
 
2402 hidnplayr 1867
        and     [eax + SOCKET.options], not (SS_ISCONNECTING)
1868
        or      [eax + SOCKET.options], SS_ISDISCONNECTING + SS_CANTRCVMORE + SS_CANTSENDMORE
1773 hidnplayr 1869
 
2402 hidnplayr 1870
        jmp     SOCKET_notify_owner
1773 hidnplayr 1871
 
1872
 
1873
 
1874
;-----------------------------------------------------------------
1875
;
1876
; SOCKET_is_disconnected
1877
;
1878
;  IN:  eax = socket ptr
1879
;  OUT: /
1880
;
1881
;-----------------------------------------------------------------
1882
 
1883
align 4
1884
SOCKET_is_disconnected:
1885
 
2891 hidnplayr 1886
        DEBUGF  1,"SOCKET_is_disconnected: %x\n", eax
1887
 
2402 hidnplayr 1888
        and     [eax + SOCKET.options], not (SS_ISCONNECTING + SS_ISCONNECTED + SS_ISDISCONNECTING)
1889
        or      [eax + SOCKET.options], SS_CANTRCVMORE + SS_CANTSENDMORE
1773 hidnplayr 1890
 
2402 hidnplayr 1891
        jmp     SOCKET_notify_owner
1774 hidnplayr 1892
 
1893
 
1894
;-----------------------------------------------------------------
1895
;
1896
; SOCKET_cant_recv_more
1897
;
1898
;  IN:  eax = socket ptr
1899
;  OUT: /
1900
;
1901
;-----------------------------------------------------------------
1902
 
1903
align 4
1904
SOCKET_cant_recv_more:
1905
 
2891 hidnplayr 1906
        DEBUGF  1,"SOCKET_cant_recv_more: %x\n", eax
1907
 
2402 hidnplayr 1908
        or      [eax + SOCKET.options], SS_CANTRCVMORE
1885 hidnplayr 1909
 
2402 hidnplayr 1910
        ret
1831 hidnplayr 1911
 
1912
 
1913
 
1914
;-----------------------------------------------------------------
1915
;
1885 hidnplayr 1916
; SOCKET_cant_send_more
1831 hidnplayr 1917
;
1918
;  IN:  eax = socket ptr
1919
;  OUT: /
1920
;
1921
;-----------------------------------------------------------------
1922
 
1923
align 4
1885 hidnplayr 1924
SOCKET_cant_send_more:
1831 hidnplayr 1925
 
2891 hidnplayr 1926
        DEBUGF  1,"SOCKET_cant_send_more: %x\n", eax
1927
 
2402 hidnplayr 1928
        or      [eax + SOCKET.options], SS_CANTSENDMORE
1831 hidnplayr 1929
 
2402 hidnplayr 1930
        ret