Subversion Repositories Kolibri OS

Rev

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

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