Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
3545 hidnplayr 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                                 ;;
8866 rgimad 3
;; Copyright (C) KolibriOS team 2004-2021. All rights reserved.    ;;
3545 hidnplayr 4
;; Distributed under terms of the GNU General Public License       ;;
5
;;                                                                 ;;
6
;;  Part of the TCP/IP network stack for KolibriOS                 ;;
7
;;                                                                 ;;
8
;;   Written by hidnplayr@kolibrios.org,                           ;;
9
;;     and Clevermouse.                                            ;;
10
;;                                                                 ;;
11
;;       Based on code by mike.dld                                 ;;
12
;;                                                                 ;;
13
;;         GNU GENERAL PUBLIC LICENSE                              ;;
14
;;          Version 2, June 1991                                   ;;
15
;;                                                                 ;;
16
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
17
 
4850 mario79 18
$Revision: 9976 $
3545 hidnplayr 19
 
20
struct  SOCKET
21
 
5976 hidnplayr 22
        NextPtr                 dd ?    ; pointer to next socket in list
23
        PrevPtr                 dd ?    ; pointer to previous socket in list
24
        Number                  dd ?    ; socket number
3545 hidnplayr 25
 
26
        mutex                   MUTEX
27
 
5976 hidnplayr 28
        PID                     dd ?    ; process ID
29
        TID                     dd ?    ; thread ID
30
        Domain                  dd ?    ; INET4/INET6/LOCAL/..
31
        Type                    dd ?    ; RAW/STREAM/DGRAM
32
        Protocol                dd ?    ; UDP/TCP/ARP/ICMP
3545 hidnplayr 33
        errorcode               dd ?
5976 hidnplayr 34
        device                  dd ?    ; device pointer, paired socket pointer if it's a local socket
3545 hidnplayr 35
 
36
        options                 dd ?
37
        state                   dd ?
5976 hidnplayr 38
        backlog                 dw ?    ; number of incoming connections that can be queued
3545 hidnplayr 39
 
40
        snd_proc                dd ?
41
        rcv_proc                dd ?
4030 hidnplayr 42
        connect_proc            dd ?
9917 Doczom 43
        ;sndto_proc              dd ?
44
        ;rcvfrom_proc            dd ?
3545 hidnplayr 45
 
46
ends
47
 
48
struct  IP_SOCKET               SOCKET
49
 
5976 hidnplayr 50
        LocalIP                 rd 4    ; network byte order
51
        RemoteIP                rd 4    ; network byte order
5842 hidnplayr 52
        ttl                     db ?
5976 hidnplayr 53
                                rb 3    ; align
3545 hidnplayr 54
 
55
ends
56
 
57
struct  TCP_SOCKET              IP_SOCKET
58
 
5976 hidnplayr 59
        LocalPort               dw ?    ; network byte order
60
        RemotePort              dw ?    ; network byte order
3545 hidnplayr 61
 
5976 hidnplayr 62
        t_state                 dd ?    ; TCB state
3545 hidnplayr 63
        t_rxtshift              db ?
5976 hidnplayr 64
                                rb 3    ; align
3545 hidnplayr 65
        t_rxtcur                dd ?
66
        t_dupacks               dd ?
67
        t_maxseg                dd ?
68
        t_flags                 dd ?
69
 
70
;---------------
71
; RFC783 page 21
72
 
73
; send sequence
5976 hidnplayr 74
        SND_UNA                 dd ?    ; sequence number of unack'ed sent Packets
75
        SND_NXT                 dd ?    ; next send sequence number to use
76
        SND_UP                  dd ?    ; urgent pointer
6476 hidnplayr 77
        SND_WL1                 dd ?    ; the sequence number of the last segment used to update the send window
78
        SND_WL2                 dd ?    ; the acknowledgment number of the last segment used to update the send window
5976 hidnplayr 79
        ISS                     dd ?    ; initial send sequence number
80
        SND_WND                 dd ?    ; send window
3545 hidnplayr 81
 
82
; receive sequence
5976 hidnplayr 83
        RCV_WND                 dd ?    ; receive window
84
        RCV_NXT                 dd ?    ; next receive sequence number to use
85
        RCV_UP                  dd ?    ; urgent pointer
86
        IRS                     dd ?    ; initial receive sequence number
3545 hidnplayr 87
 
88
;---------------------
89
; Additional variables
90
 
91
; receive variables
92
        RCV_ADV                 dd ?
93
 
94
; retransmit variables
95
        SND_MAX                 dd ?
96
 
97
; congestion control
4339 hidnplayr 98
        SND_CWND                dd ?    ; congestion window
99
        SND_SSTHRESH            dd ?    ; slow start threshold
3545 hidnplayr 100
 
101
;----------------------
102
; Transmit timing stuff
103
        t_idle                  dd ?
5442 hidnplayr 104
        t_rtt                   dd ?    ; round trip time
3545 hidnplayr 105
        t_rtseq                 dd ?
5442 hidnplayr 106
        t_srtt                  dd ?    ; smoothed round trip time
3545 hidnplayr 107
        t_rttvar                dd ?
108
        t_rttmin                dd ?
109
        max_sndwnd              dd ?
110
 
111
;-----------------
112
; Out-of-band data
113
        t_oobflags              dd ?
114
        t_iobc                  dd ?
115
        t_softerror             dd ?
116
 
117
 
118
;---------
119
; RFC 1323                              ; the order of next 4 elements may not change
120
 
121
        SND_SCALE               db ?
122
        RCV_SCALE               db ?
123
        requested_s_scale       db ?
124
        request_r_scale         db ?
125
 
126
        ts_recent               dd ?    ; a copy of the most-recent valid timestamp from the other end
127
        ts_recent_age           dd ?
128
        last_ack_sent           dd ?
129
 
130
 
131
;-------
132
; Timers
3600 hidnplayr 133
        timer_flags             dd ?
5976 hidnplayr 134
        timer_retransmission    dd ?    ; rexmt
3545 hidnplayr 135
        timer_persist           dd ?
5976 hidnplayr 136
        timer_keepalive         dd ?    ; keepalive/syn timeout
137
        timer_timed_wait        dd ?    ; also used as 2msl timer
4021 hidnplayr 138
        timer_connect           dd ?
3545 hidnplayr 139
 
140
; extra
141
 
5976 hidnplayr 142
        ts_ecr                  dd ?    ; timestamp echo reply
3545 hidnplayr 143
        ts_val                  dd ?
144
 
5976 hidnplayr 145
        seg_next                dd ?    ; re-assembly queue
3545 hidnplayr 146
 
147
ends
148
 
149
struct  UDP_SOCKET              IP_SOCKET
150
 
5976 hidnplayr 151
        LocalPort               dw ?    ; in network byte order
152
        RemotePort              dw ?    ; in network byte order
3545 hidnplayr 153
 
154
ends
155
 
156
struct  RING_BUFFER
157
 
158
        mutex                   MUTEX
5976 hidnplayr 159
        start_ptr               dd ?    ; Pointer to start of buffer
160
        end_ptr                 dd ?    ; pointer to end of buffer
161
        read_ptr                dd ?    ; Read pointer
162
        write_ptr               dd ?    ; Write pointer
163
        size                    dd ?    ; Number of bytes buffered
3545 hidnplayr 164
 
165
ends
166
 
167
struct  STREAM_SOCKET           TCP_SOCKET
168
 
169
        rcv                     RING_BUFFER
170
        snd                     RING_BUFFER
171
 
172
ends
173
 
9739 turbocat 174
struct sockaddr
175
 
176
        family                  dw ?    ; Address family
177
        port                    dw ?    ; 16 bit TCP/UDP port number
178
        ip                      dd ?    ; 32 bit IP address
179
        _zero                   rb 8    ; Not use, for align
180
 
181
ends
182
 
3545 hidnplayr 183
struct  socket_queue_entry
184
 
185
        data_ptr                dd ?
5522 hidnplayr 186
        data_size               dd ?
3545 hidnplayr 187
        buf_ptr                 dd ?
188
 
189
ends
190
 
5976 hidnplayr 191
struct  socket_options
3545 hidnplayr 192
 
5976 hidnplayr 193
        level                   dd ?
194
        optname                 dd ?
195
        optlen                  dd ?
196
        optval                  dd ?
3545 hidnplayr 197
 
5976 hidnplayr 198
ends
199
 
6413 hidnplayr 200
SOCKET_STRUCT_SIZE      = 4096          ; in bytes
5976 hidnplayr 201
 
202
SOCKET_QUEUE_SIZE       = 10            ; maximum number of incoming packets queued for 1 socket
3545 hidnplayr 203
; the incoming packet queue for sockets is placed in the socket struct itself, at this location from start
6413 hidnplayr 204
SOCKET_QUEUE_LOCATION   = (SOCKET_STRUCT_SIZE - SOCKET_QUEUE_SIZE*sizeof.socket_queue_entry - sizeof.queue)
3545 hidnplayr 205
 
206
uglobal
3698 hidnplayr 207
align 4
208
 
3545 hidnplayr 209
        net_sockets     rd 4
210
        last_socket_num dd ?
5976 hidnplayr 211
        last_UDP_port   dw ?            ; last used ephemeral port
212
        last_TCP_port   dw ?            ;
3647 hidnplayr 213
        socket_mutex    MUTEX
3698 hidnplayr 214
 
3545 hidnplayr 215
endg
216
 
217
 
5976 hidnplayr 218
;-----------------------------------------------------------------;
219
;                                                                 ;
6011 hidnplayr 220
; socket_init                                                     ;
5976 hidnplayr 221
;                                                                 ;
222
;-----------------------------------------------------------------;
6011 hidnplayr 223
macro   socket_init {
3545 hidnplayr 224
 
225
        xor     eax, eax
226
        mov     edi, net_sockets
227
        mov     ecx, 5
3711 clevermous 228
        rep stosd
3545 hidnplayr 229
 
230
       @@:
231
        pseudo_random eax
3600 hidnplayr 232
        cmp     ax, EPHEMERAL_PORT_MIN
3545 hidnplayr 233
        jb      @r
3600 hidnplayr 234
        cmp     ax, EPHEMERAL_PORT_MAX
3545 hidnplayr 235
        ja      @r
236
        xchg    al, ah
237
        mov     [last_UDP_port], ax
238
 
239
       @@:
240
        pseudo_random eax
3600 hidnplayr 241
        cmp     ax, EPHEMERAL_PORT_MIN
3545 hidnplayr 242
        jb      @r
3600 hidnplayr 243
        cmp     ax, EPHEMERAL_PORT_MAX
3545 hidnplayr 244
        ja      @r
245
        xchg    al, ah
246
        mov     [last_TCP_port], ax
247
 
3647 hidnplayr 248
        mov     ecx, socket_mutex
249
        call    mutex_init
250
 
3545 hidnplayr 251
}
252
 
5976 hidnplayr 253
;-----------------------------------------------------------------;
254
;                                                                 ;
255
; Sockets API (system function 75)                                ;
256
;                                                                 ;
257
;-----------------------------------------------------------------;
3545 hidnplayr 258
align 4
259
sys_socket:
260
 
9917 Doczom 261
        mov     dword[esp + SYSCALL_STACK.ebx], 0        ; Set error code to 0
3659 hidnplayr 262
 
3545 hidnplayr 263
        cmp     ebx, 255
6011 hidnplayr 264
        jz      socket_debug
3545 hidnplayr 265
 
266
        cmp     ebx, .number
3658 hidnplayr 267
        ja      .error
3545 hidnplayr 268
        jmp     dword [.table + 4*ebx]
269
 
270
  .table:
6011 hidnplayr 271
        dd      socket_open             ; 0
272
        dd      socket_close            ; 1
273
        dd      socket_bind             ; 2
274
        dd      socket_listen           ; 3
275
        dd      socket_connect          ; 4
276
        dd      socket_accept           ; 5
277
        dd      socket_send             ; 6
278
        dd      socket_receive          ; 7
279
        dd      socket_set_opt          ; 8
280
        dd      socket_get_opt          ; 9
281
        dd      socket_pair             ; 10
9917 Doczom 282
 
283
        ;dd      socket_sendto           ; 11
284
        ;dd      socket_recvfrom         ; 12
3545 hidnplayr 285
  .number = ($ - .table) / 4 - 1
286
 
3658 hidnplayr 287
  .error:
9917 Doczom 288
        mov     dword[esp + SYSCALL_STACK.eax], -1
289
        mov     dword[esp + SYSCALL_STACK.ebx], EINVAL
3545 hidnplayr 290
 
291
        ret
292
 
5976 hidnplayr 293
;-----------------------------------------------------------------;
294
;                                                                 ;
6011 hidnplayr 295
; socket_open: Create a new socket.                               ;
5976 hidnplayr 296
;                                                                 ;
297
;   IN: ecx = domain                                              ;
298
;       edx = type                                                ;
299
;       esi = protocol                                            ;
300
;                                                                 ;
301
;  OUT: eax = socket number                                       ;
302
;       eax = -1 on error                                         ;
303
;       ebx = errorcode on error                                  ;
304
;                                                                 ;
305
;-----------------------------------------------------------------;
3545 hidnplayr 306
align 4
6011 hidnplayr 307
socket_open:
3545 hidnplayr 308
 
7974 hidnplayr 309
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_open: domain=%u type=%u protocol=%x\n", ecx, edx, esi
3545 hidnplayr 310
 
311
        push    ecx edx esi
6011 hidnplayr 312
        call    socket_alloc
3545 hidnplayr 313
        pop     esi edx ecx
4535 hidnplayr 314
        test    eax, eax
3658 hidnplayr 315
        jz      .nobuffs
3545 hidnplayr 316
 
9917 Doczom 317
        mov     [esp + SYSCALL_STACK.eax], edi    ; return socketnumber
7974 hidnplayr 318
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_open: socknum=%u\n", edi
3545 hidnplayr 319
 
3705 hidnplayr 320
        test    edx, SO_NONBLOCK
321
        jz      @f
322
        or      [eax + SOCKET.options], SO_NONBLOCK
323
        and     edx, not SO_NONBLOCK
324
  @@:
3545 hidnplayr 325
 
326
        mov     [eax + SOCKET.Domain], ecx
327
        mov     [eax + SOCKET.Type], edx
328
        mov     [eax + SOCKET.Protocol], esi
4030 hidnplayr 329
        mov     [eax + SOCKET.connect_proc], connect_notsupp
3545 hidnplayr 330
 
331
        cmp     ecx, AF_INET4
332
        jne     .no_inet4
333
 
5842 hidnplayr 334
        mov     [eax + IP_SOCKET.ttl], 128
335
 
3545 hidnplayr 336
        cmp     edx, SOCK_DGRAM
337
        je      .udp
338
 
339
        cmp     edx, SOCK_STREAM
340
        je      .tcp
341
 
342
        cmp     edx, SOCK_RAW
343
        je      .raw
344
 
345
  .no_inet4:
346
        cmp     ecx, AF_PPP
347
        jne     .no_ppp
348
 
9049 hidnplayr 349
;        cmp     esi, PPP_PROTO_ETHERNET
350
;        je      .pppoe
3545 hidnplayr 351
 
352
  .no_ppp:
3658 hidnplayr 353
  .unsupported:
354
        push    eax
6011 hidnplayr 355
        call    socket_free
3658 hidnplayr 356
        pop     eax
9917 Doczom 357
        mov     dword[esp + SYSCALL_STACK.ebx], EOPNOTSUPP
358
        mov     dword[esp + SYSCALL_STACK.eax], -1
3545 hidnplayr 359
        ret
360
 
3658 hidnplayr 361
  .nobuffs:
9917 Doczom 362
        mov     dword[esp + SYSCALL_STACK.ebx], ENOBUFS
363
        mov     dword[esp + SYSCALL_STACK.eax], -1
3658 hidnplayr 364
        ret
365
 
3545 hidnplayr 366
  .raw:
5976 hidnplayr 367
        test    esi, esi        ; IP_PROTO_IP
3658 hidnplayr 368
        jz      .raw_ip
3545 hidnplayr 369
 
370
        cmp     esi, IP_PROTO_ICMP
3658 hidnplayr 371
        je      .raw_icmp
3545 hidnplayr 372
 
3658 hidnplayr 373
        jmp     .unsupported
3545 hidnplayr 374
 
375
align 4
376
  .udp:
5842 hidnplayr 377
        push    eax
378
        init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
379
        pop     eax
380
 
3545 hidnplayr 381
        mov     [eax + SOCKET.Protocol], IP_PROTO_UDP
6011 hidnplayr 382
        mov     [eax + SOCKET.snd_proc], socket_send_udp
383
        mov     [eax + SOCKET.rcv_proc], socket_receive_dgram
384
        mov     [eax + SOCKET.connect_proc], udp_connect
3545 hidnplayr 385
        ret
386
 
387
align 4
388
  .tcp:
389
        mov     [eax + SOCKET.Protocol], IP_PROTO_TCP
6011 hidnplayr 390
        mov     [eax + SOCKET.snd_proc], socket_send_tcp
7974 hidnplayr 391
        mov     [eax + SOCKET.rcv_proc], socket_receive_tcp
6011 hidnplayr 392
        mov     [eax + SOCKET.connect_proc], tcp_connect
3545 hidnplayr 393
 
6011 hidnplayr 394
        tcp_init_socket eax
3545 hidnplayr 395
        ret
396
 
397
 
398
align 4
3658 hidnplayr 399
  .raw_ip:
5842 hidnplayr 400
        push    eax
401
        init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
402
        pop     eax
403
 
6011 hidnplayr 404
        mov     [eax + SOCKET.snd_proc], socket_send_ip
405
        mov     [eax + SOCKET.rcv_proc], socket_receive_dgram
406
        mov     [eax + SOCKET.connect_proc], ipv4_connect
3545 hidnplayr 407
        ret
408
 
409
 
410
align 4
3658 hidnplayr 411
  .raw_icmp:
5842 hidnplayr 412
        push    eax
413
        init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
414
        pop     eax
415
 
6011 hidnplayr 416
        mov     [eax + SOCKET.snd_proc], socket_send_icmp
417
        mov     [eax + SOCKET.rcv_proc], socket_receive_dgram
418
        mov     [eax + SOCKET.connect_proc], ipv4_connect
3545 hidnplayr 419
        ret
420
 
9049 hidnplayr 421
;align 4
422
;  .pppoe:
423
;        push    eax
424
;        init_queue (eax + SOCKET_QUEUE_LOCATION)        ; Set up data receiving queue
425
;        pop     eax
426
;
427
;        mov     [eax + SOCKET.snd_proc], socket_send_pppoe
428
;        mov     [eax + SOCKET.rcv_proc], socket_receive_dgram
429
;        ret
3545 hidnplayr 430
 
431
 
5976 hidnplayr 432
;-----------------------------------------------------------------;
433
;                                                                 ;
6011 hidnplayr 434
; socket_bind: Bind to a local port.                              ;
5976 hidnplayr 435
;                                                                 ;
436
;   IN: ecx = socket number                                       ;
437
;       edx = pointer to sockaddr struct                          ;
438
;       esi = length of sockaddr struct                           ;
439
;                                                                 ;
440
;  OUT: eax = 0 on success                                        ;
441
;       eax = -1 on error                                         ;
442
;       ebx = errorcode on error                                  ;
443
;                                                                 ;
444
;-----------------------------------------------------------------;
3545 hidnplayr 445
align 4
6011 hidnplayr 446
socket_bind:
3545 hidnplayr 447
 
3556 hidnplayr 448
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_bind: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
3545 hidnplayr 449
 
6011 hidnplayr 450
        call    socket_num_to_ptr
5969 hidnplayr 451
        test    eax, eax
3658 hidnplayr 452
        jz      .invalid
3545 hidnplayr 453
 
454
        cmp     esi, 2
3658 hidnplayr 455
        jb      .invalid
3545 hidnplayr 456
 
5976 hidnplayr 457
        cmp     [eax + UDP_SOCKET.LocalPort], 0 ; Socket can only be bound once
4052 hidnplayr 458
        jnz     .invalid
459
 
6011 hidnplayr 460
        cmp     word[edx], AF_INET4
3545 hidnplayr 461
        je      .af_inet4
462
 
6011 hidnplayr 463
        cmp     word[edx], AF_LOCAL
3545 hidnplayr 464
        je      .af_local
465
 
3658 hidnplayr 466
  .notsupp:
9917 Doczom 467
        mov     dword[esp + SYSCALL_STACK.ebx], EOPNOTSUPP
468
        mov     dword[esp + SYSCALL_STACK.eax], -1
3658 hidnplayr 469
        ret
3545 hidnplayr 470
 
3658 hidnplayr 471
  .invalid:
9917 Doczom 472
        mov     dword[esp + SYSCALL_STACK.ebx], EINVAL
473
        mov     dword[esp + SYSCALL_STACK.eax], -1
3658 hidnplayr 474
        ret
475
 
3545 hidnplayr 476
  .af_local:
477
        ; TODO: write code here
9917 Doczom 478
        mov     dword[esp + SYSCALL_STACK.eax], 0
3545 hidnplayr 479
        ret
480
 
481
  .af_inet4:
482
        cmp     esi, 6
3658 hidnplayr 483
        jb      .invalid
3545 hidnplayr 484
 
485
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
486
        je      .udp
487
 
488
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
489
        je      .tcp
490
 
3658 hidnplayr 491
        jmp     .notsupp
3545 hidnplayr 492
 
493
  .tcp:
494
  .udp:
4052 hidnplayr 495
        pushd   [edx + 4]                       ; First, fill in the IP
496
        popd    [eax + IP_SOCKET.LocalIP]
3545 hidnplayr 497
 
4052 hidnplayr 498
        mov     bx, [edx + 2]                   ; Did caller specify a local port?
499
        test    bx, bx
500
        jnz     .just_check
6011 hidnplayr 501
        call    socket_find_port                ; Nope, find an ephemeral one
4052 hidnplayr 502
        jmp     .done
503
 
504
  .just_check:
6011 hidnplayr 505
        call    socket_check_port               ; Yes, check if it's still available
4052 hidnplayr 506
        jz      .addrinuse                      ; ZF is set by socket_check_port on error
507
 
508
  .done:
3556 hidnplayr 509
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_bind: local ip=%u.%u.%u.%u\n",\
3545 hidnplayr 510
        [eax + IP_SOCKET.LocalIP + 0]:1,[eax + IP_SOCKET.LocalIP + 1]:1,\
511
        [eax + IP_SOCKET.LocalIP + 2]:1,[eax + IP_SOCKET.LocalIP + 3]:1
512
 
9917 Doczom 513
        mov     dword[esp + SYSCALL_STACK.eax], 0
3545 hidnplayr 514
        ret
515
 
3658 hidnplayr 516
  .addrinuse:
9917 Doczom 517
        mov     dword[esp + SYSCALL_STACK.eax], -1
518
        mov     dword[esp + SYSCALL_STACK.ebx], EADDRINUSE
3658 hidnplayr 519
        ret
3545 hidnplayr 520
 
521
 
522
 
3658 hidnplayr 523
 
5976 hidnplayr 524
;-----------------------------------------------------------------;
525
;                                                                 ;
6011 hidnplayr 526
; socket_connect: Connect to the remote host.                     ;
5976 hidnplayr 527
;                                                                 ;
528
;   IN: ecx = socket number                                       ;
529
;       edx = pointer to sockaddr struct                          ;
530
;       esi = length of sockaddr struct                           ;
531
;                                                                 ;
532
;  OUT: eax = 0 on success                                        ;
533
;       eax = -1 on error                                         ;
534
;       ebx = errorcode on error                                  ;
535
;                                                                 ;
536
;-----------------------------------------------------------------;
3545 hidnplayr 537
align 4
6011 hidnplayr 538
socket_connect:
3545 hidnplayr 539
 
3556 hidnplayr 540
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_connect: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
3545 hidnplayr 541
 
6011 hidnplayr 542
        call    socket_num_to_ptr
5969 hidnplayr 543
        test    eax, eax
3658 hidnplayr 544
        jz      .invalid
3545 hidnplayr 545
 
546
        cmp     esi, 8
3658 hidnplayr 547
        jb      .invalid
3545 hidnplayr 548
 
4025 hidnplayr 549
        cmp     [eax + SOCKET.state], SS_ISCONNECTING
550
        je      .already
551
 
552
        test    [eax + SOCKET.options], SO_ACCEPTCON
553
        jnz     .notsupp
554
 
4030 hidnplayr 555
        call    [eax + SOCKET.connect_proc]
3545 hidnplayr 556
 
9917 Doczom 557
        mov     dword[esp + SYSCALL_STACK.ebx], ebx
558
        mov     dword[esp + SYSCALL_STACK.eax], eax
4030 hidnplayr 559
        ret
560
 
561
 
3658 hidnplayr 562
  .notsupp:
9917 Doczom 563
        mov     dword[esp + SYSCALL_STACK.ebx], EOPNOTSUPP
564
        mov     dword[esp + SYSCALL_STACK.eax], -1
3658 hidnplayr 565
        ret
3545 hidnplayr 566
 
3658 hidnplayr 567
  .invalid:
9917 Doczom 568
        mov     dword[esp + SYSCALL_STACK.ebx], EINVAL
569
        mov     dword[esp + SYSCALL_STACK.eax], -1
3658 hidnplayr 570
        ret
571
 
4025 hidnplayr 572
  .already:
9917 Doczom 573
        mov     dword[esp + SYSCALL_STACK.ebx], EALREADY
574
        mov     dword[esp + SYSCALL_STACK.eax], -1
4025 hidnplayr 575
        ret
576
 
577
 
4030 hidnplayr 578
connect_notsupp:
579
        xor     eax, eax
580
        dec     eax
581
        mov     ebx, EOPNOTSUPP
3545 hidnplayr 582
        ret
583
 
4025 hidnplayr 584
 
5976 hidnplayr 585
;-----------------------------------------------------------------;
586
;                                                                 ;
6011 hidnplayr 587
; socket_listen: Listen for incoming connections.                 ;
5976 hidnplayr 588
;                                                                 ;
589
;   IN: ecx = socket number                                       ;
590
;       edx = backlog in edx                                      ;
591
;                                                                 ;
592
;  OUT: eax = 0 on success                                        ;
593
;       eax = -1 on error                                         ;
594
;       ebx = errorcode on error                                  ;
595
;                                                                 ;
596
;-----------------------------------------------------------------;
3545 hidnplayr 597
align 4
6011 hidnplayr 598
socket_listen:
3545 hidnplayr 599
 
3556 hidnplayr 600
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_listen: socknum=%u backlog=%u\n", ecx, edx
3545 hidnplayr 601
 
6011 hidnplayr 602
        call    socket_num_to_ptr
5969 hidnplayr 603
        test    eax, eax
3658 hidnplayr 604
        jz      .invalid
3545 hidnplayr 605
 
606
        cmp     [eax + SOCKET.Domain], AF_INET4
3658 hidnplayr 607
        jne     .notsupp
3545 hidnplayr 608
 
609
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
3658 hidnplayr 610
        jne     .invalid
3545 hidnplayr 611
 
612
        cmp     [eax + TCP_SOCKET.LocalPort], 0
3658 hidnplayr 613
        je      .already
3545 hidnplayr 614
 
615
        cmp     [eax + IP_SOCKET.LocalIP], 0
616
        jne     @f
7678 hidnplayr 617
        push    [IPv4_address + 4]           ;;; fixme!!!!
3545 hidnplayr 618
        pop     [eax + IP_SOCKET.LocalIP]
619
       @@:
620
 
621
        cmp     edx, MAX_backlog
622
        jbe     @f
623
        mov     edx, MAX_backlog
624
       @@:
625
 
626
        mov     [eax + SOCKET.backlog], dx
627
        or      [eax + SOCKET.options], SO_ACCEPTCON
628
        mov     [eax + TCP_SOCKET.t_state], TCPS_LISTEN
629
        mov     [eax + TCP_SOCKET.timer_keepalive], 0           ; disable keepalive timer
630
 
631
        push    eax
632
        init_queue (eax + SOCKET_QUEUE_LOCATION)                ; Set up sockets queue
633
        pop     eax
634
 
9917 Doczom 635
        mov     dword[esp + SYSCALL_STACK.eax], 0
3658 hidnplayr 636
        ret
3545 hidnplayr 637
 
3658 hidnplayr 638
  .notsupp:
9917 Doczom 639
        mov     dword[esp + SYSCALL_STACK.ebx], EOPNOTSUPP
640
        mov     dword[esp + SYSCALL_STACK.eax], -1
3545 hidnplayr 641
        ret
642
 
3658 hidnplayr 643
  .invalid:
9917 Doczom 644
        mov     dword[esp + SYSCALL_STACK.ebx], EINVAL
645
        mov     dword[esp + SYSCALL_STACK.eax], -1
3658 hidnplayr 646
        ret
3545 hidnplayr 647
 
3658 hidnplayr 648
  .already:
9917 Doczom 649
        mov     dword[esp + SYSCALL_STACK.ebx], EALREADY
650
        mov     dword[esp + SYSCALL_STACK.eax], -1
3658 hidnplayr 651
        ret
652
 
653
 
5976 hidnplayr 654
;-----------------------------------------------------------------;
655
;                                                                 ;
6011 hidnplayr 656
; socket_accept: Accept an incoming connection.                   ;
5976 hidnplayr 657
;                                                                 ;
658
;   IN: ecx = socket number (of listening socket)                 ;
659
;       edx = ptr to sockaddr struct                              ;
660
;       esi = length of sockaddr struct                           ;
661
;                                                                 ;
662
;  OUT: eax = newly created socket num                            ;
663
;       eax = -1 on error                                         ;
664
;       ebx = errorcode on error                                  ;
665
;                                                                 ;
666
;-----------------------------------------------------------------;
3545 hidnplayr 667
align 4
6011 hidnplayr 668
socket_accept:
3545 hidnplayr 669
 
3556 hidnplayr 670
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_accept: socknum=%u sockaddr=%x length=%u\n", ecx, edx, esi
3545 hidnplayr 671
 
6011 hidnplayr 672
        call    socket_num_to_ptr
5969 hidnplayr 673
        test    eax, eax
3658 hidnplayr 674
        jz      .invalid
3545 hidnplayr 675
 
676
        test    [eax + SOCKET.options], SO_ACCEPTCON
3658 hidnplayr 677
        jz      .invalid
3545 hidnplayr 678
 
679
        cmp     [eax + SOCKET.Domain], AF_INET4
3658 hidnplayr 680
        jne     .notsupp
3545 hidnplayr 681
 
682
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
3658 hidnplayr 683
        jne     .invalid
3545 hidnplayr 684
 
685
  .loop:
686
        get_from_queue (eax + SOCKET_QUEUE_LOCATION), MAX_backlog, 4, .block
687
 
688
; Ok, we got a socket ptr
689
        mov     eax, [esi]
690
 
5969 hidnplayr 691
; Verify that it is (still) a valid socket
6011 hidnplayr 692
        call    socket_check
5969 hidnplayr 693
        jz      .invalid
694
 
695
; Change sockets thread owner ID to that of the current thread
9692 Doczom 696
        mov     ebx, [current_slot]
697
        mov     ebx, [ebx + APPDATA.tid]
3545 hidnplayr 698
        mov     [eax + SOCKET.TID], ebx
699
 
5969 hidnplayr 700
; Return socket number to caller
701
        mov     eax, [eax + SOCKET.Number]
9917 Doczom 702
        mov     [esp + SYSCALL_STACK.eax], eax
3545 hidnplayr 703
        ret
704
 
705
  .block:
706
        test    [eax + SOCKET.options], SO_NONBLOCK
3658 hidnplayr 707
        jnz     .wouldblock
6908 ashmew2 708
 
6011 hidnplayr 709
        call    socket_block
3545 hidnplayr 710
        jmp     .loop
711
 
3658 hidnplayr 712
  .wouldblock:
9917 Doczom 713
        mov     dword[esp + SYSCALL_STACK.ebx], EWOULDBLOCK
714
        mov     dword[esp + SYSCALL_STACK.eax], -1
3658 hidnplayr 715
        ret
716
 
717
  .invalid:
9917 Doczom 718
        mov     dword[esp + SYSCALL_STACK.ebx], EINVAL
719
        mov     dword[esp + SYSCALL_STACK.eax], -1
3658 hidnplayr 720
        ret
721
 
722
  .notsupp:
9917 Doczom 723
        mov     dword[esp + SYSCALL_STACK.ebx], EOPNOTSUPP
724
        mov     dword[esp + SYSCALL_STACK.eax], -1
3658 hidnplayr 725
        ret
726
 
5976 hidnplayr 727
;-----------------------------------------------------------------;
728
;                                                                 ;
6011 hidnplayr 729
; socket_close: Close the socket (and connection).                ;
5976 hidnplayr 730
;                                                                 ;
731
;   IN: ecx = socket number                                       ;
732
;                                                                 ;
733
;  OUT: eax = 0 on success                                        ;
734
;       eax = -1 on error                                         ;
735
;       ebx = errorcode on error                                  ;
736
;                                                                 ;
737
;-----------------------------------------------------------------;
3545 hidnplayr 738
align 4
6011 hidnplayr 739
socket_close:
3545 hidnplayr 740
 
3556 hidnplayr 741
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_close: socknum=%u\n", ecx
3545 hidnplayr 742
 
6011 hidnplayr 743
        call    socket_num_to_ptr
5969 hidnplayr 744
        test    eax, eax
3658 hidnplayr 745
        jz      .invalid
3545 hidnplayr 746
 
9917 Doczom 747
        mov     dword[esp + SYSCALL_STACK.eax], 0               ; The socket exists, so we will succeed in closing it.
3545 hidnplayr 748
 
749
        or      [eax + SOCKET.options], SO_NONBLOCK             ; Mark the socket as non blocking, we dont want it to block any longer!
750
 
751
        test    [eax + SOCKET.state], SS_BLOCKED                ; Is the socket still in blocked state?
752
        jz      @f
6011 hidnplayr 753
        call    socket_notify                                   ; Unblock it.
3545 hidnplayr 754
  @@:
755
 
756
        cmp     [eax + SOCKET.Domain], AF_INET4
757
        jne     .free
758
 
759
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
9976 Jurgen 760
        jne     .free
8026 hidnplayr 761
        test    [eax + SOCKET.state], SS_ISCONNECTED
9976 Jurgen 762
        jz      .free
8026 hidnplayr 763
        test    [eax + SOCKET.state], SS_ISDISCONNECTING
9976 Jurgen 764
        jnz     .free
8026 hidnplayr 765
        call    tcp_disconnect
9976 Jurgen 766
        test    eax, eax
767
        jz      .end
768
  .free:
769
        call    socket_free
770
  .end:
3545 hidnplayr 771
        ret
772
 
773
 
3658 hidnplayr 774
  .invalid:
9917 Doczom 775
        mov     dword[esp + SYSCALL_STACK.ebx], EINVAL
776
        mov     dword[esp + SYSCALL_STACK.eax], -1
3658 hidnplayr 777
        ret
778
 
779
 
5976 hidnplayr 780
;-----------------------------------------------------------------;
781
;                                                                 ;
6011 hidnplayr 782
; socket_receive: Receive some data from the remote end.          ;
5976 hidnplayr 783
;                                                                 ;
784
;   IN: ecx = socket number                                       ;
785
;       edx = addr to application buffer                          ;
9049 hidnplayr 786
;       esi = length of application buffer                        ;
5976 hidnplayr 787
;       edi = flags                                               ;
788
;                                                                 ;
789
;  OUT: eax = number of bytes copied                              ;
790
;       eax = -1 on error                                         ;
791
;       eax = 0 when socket has been closed by the remote end     ;
792
;       ebx = errorcode on error                                  ;
793
;                                                                 ;
794
;-----------------------------------------------------------------;
3545 hidnplayr 795
align 4
6011 hidnplayr 796
socket_receive:
3545 hidnplayr 797
 
3556 hidnplayr 798
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: socknum=%u bufaddr=%x buflength=%u flags=%x\n", ecx, edx, esi, edi
3545 hidnplayr 799
 
6011 hidnplayr 800
        call    socket_num_to_ptr
5969 hidnplayr 801
        test    eax, eax
3658 hidnplayr 802
        jz      .invalid
3545 hidnplayr 803
 
9049 hidnplayr 804
        stdcall is_region_userspace, edx, esi
805
        jnz     .invalid
806
 
3704 hidnplayr 807
  .loop:
808
        push    edi
3565 hidnplayr 809
        call    [eax + SOCKET.rcv_proc]
3704 hidnplayr 810
        pop     edi
3545 hidnplayr 811
 
4219 hidnplayr 812
        test    [eax + SOCKET.state], SS_CANTRCVMORE
5364 hidnplayr 813
        jnz     .last_data
4219 hidnplayr 814
 
3704 hidnplayr 815
        cmp     ebx, EWOULDBLOCK
816
        jne     .return
817
 
818
        test    edi, MSG_DONTWAIT
819
        jnz     .return_err
820
 
5976 hidnplayr 821
        test    [eax + SOCKET.options], SO_NONBLOCK
822
        jnz     .return_err
6908 ashmew2 823
 
6011 hidnplayr 824
        call    socket_block
3704 hidnplayr 825
        jmp     .loop
826
 
827
 
828
  .invalid:
829
        push    EINVAL
830
        pop     ebx
831
  .return_err:
4219 hidnplayr 832
        mov     ecx, -1
3704 hidnplayr 833
  .return:
9917 Doczom 834
        mov     [esp + SYSCALL_STACK.ebx], ebx
835
        mov     [esp + SYSCALL_STACK.eax], ecx
3565 hidnplayr 836
        ret
3545 hidnplayr 837
 
5364 hidnplayr 838
  .last_data:
839
        test    ecx, ecx
840
        jz      .return
6011 hidnplayr 841
        call    socket_notify                                   ; Call me again!
5364 hidnplayr 842
        jmp     .return
3565 hidnplayr 843
 
3658 hidnplayr 844
 
3704 hidnplayr 845
 
846
 
3545 hidnplayr 847
align 4
6011 hidnplayr 848
socket_receive_dgram:
3704 hidnplayr 849
 
3556 hidnplayr 850
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: DGRAM\n"
3545 hidnplayr 851
 
5976 hidnplayr 852
        test    edi, MSG_PEEK
853
        jnz     .peek
3545 hidnplayr 854
 
5976 hidnplayr 855
        mov     ebx, esi                                        ; buffer length
856
 
3704 hidnplayr 857
        get_from_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, .wouldblock ; sets esi only on success.
3545 hidnplayr 858
        mov     ecx, [esi + socket_queue_entry.data_size]
3556 hidnplayr 859
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: %u bytes data\n", ecx
3545 hidnplayr 860
 
3704 hidnplayr 861
        cmp     ecx, ebx                                        ; If data segment does not fit in applications buffer, abort
3545 hidnplayr 862
        ja      .too_small
863
 
4219 hidnplayr 864
        push    eax ecx
3545 hidnplayr 865
        push    [esi + socket_queue_entry.buf_ptr]              ; save the buffer addr so we can clear it later
866
        mov     esi, [esi + socket_queue_entry.data_ptr]
3556 hidnplayr 867
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: Source buffer=%x real addr=%x\n", [esp], esi
3545 hidnplayr 868
 
3704 hidnplayr 869
; copy the data from kernel buffer to application buffer
870
        mov     edi, edx                                        ; bufferaddr
3545 hidnplayr 871
        shr     ecx, 1
872
        jnc     .nb
873
        movsb
874
  .nb:
875
        shr     ecx, 1
876
        jnc     .nw
877
        movsw
878
  .nw:
879
        test    ecx, ecx
880
        jz      .nd
3711 clevermous 881
        rep movsd
3545 hidnplayr 882
  .nd:
883
 
6011 hidnplayr 884
        call    net_buff_free
4219 hidnplayr 885
        pop     ecx eax                                         ; return number of bytes copied to application
5976 hidnplayr 886
        cmp     [eax + SOCKET_QUEUE_LOCATION + queue.size], 0
887
        je      @f
6011 hidnplayr 888
        call    socket_notify                                   ; Queue another network event
5976 hidnplayr 889
  @@:
890
        xor     ebx, ebx                                        ; errorcode = 0 (no error)
3545 hidnplayr 891
        ret
892
 
893
  .too_small:
4219 hidnplayr 894
        mov     ecx, -1
3704 hidnplayr 895
        push    EMSGSIZE
896
        pop     ebx
3565 hidnplayr 897
        ret
3545 hidnplayr 898
 
3658 hidnplayr 899
  .wouldblock:
3704 hidnplayr 900
        push    EWOULDBLOCK
901
        pop     ebx
3658 hidnplayr 902
        ret
3545 hidnplayr 903
 
5976 hidnplayr 904
  .peek:
905
        xor     ebx, ebx
906
        xor     ecx, ecx
907
        cmp     [eax + SOCKET_QUEUE_LOCATION + queue.size], 0
908
        je      @f
909
        mov     esi, [eax + SOCKET_QUEUE_LOCATION + queue.r_ptr]
910
        mov     ecx, [esi + socket_queue_entry.data_size]
911
  @@:
912
        ret
3658 hidnplayr 913
 
7974 hidnplayr 914
align 4
915
socket_receive_tcp:
3704 hidnplayr 916
 
7974 hidnplayr 917
        call    socket_receive_stream
918
 
919
        test    ecx, ecx
920
        jz      @f
921
        push    eax ebx ecx
922
        call    tcp_output
923
        pop     ecx ebx eax
924
  @@:
925
 
926
        ret
927
 
928
 
3545 hidnplayr 929
align 4
6011 hidnplayr 930
socket_receive_local:
3545 hidnplayr 931
 
932
        ; does this socket have a PID yet?
933
        cmp     [eax + SOCKET.PID], 0
934
        jne     @f
935
 
936
        ; Change PID to that of current process
9692 Doczom 937
        mov     ebx, [current_slot]
938
        mov     ebx, [ebx + APPDATA.tid]
3545 hidnplayr 939
        mov     [eax + SOCKET.PID], ebx
3704 hidnplayr 940
        mov     [eax + SOCKET.TID], ebx                         ; currently TID = PID in kolibrios :(
3545 hidnplayr 941
      @@:
942
 
6011 hidnplayr 943
        mov     [eax + SOCKET.rcv_proc], socket_receive_stream
3545 hidnplayr 944
 
3704 hidnplayr 945
; ... continue to SOCKET_receive_stream
946
 
3545 hidnplayr 947
align 4
6011 hidnplayr 948
socket_receive_stream:
3545 hidnplayr 949
 
3556 hidnplayr 950
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_receive: STREAM\n"
3545 hidnplayr 951
 
7680 hidnplayr 952
        cmp     [eax + STREAM_SOCKET.rcv.size], 0
3704 hidnplayr 953
        je      .wouldblock
954
 
955
        test    edi, MSG_PEEK
956
        jnz     .peek
957
 
3545 hidnplayr 958
        mov     ecx, esi
959
        mov     edi, edx
960
        xor     edx, edx
961
 
4219 hidnplayr 962
        push    eax
3545 hidnplayr 963
        add     eax, STREAM_SOCKET.rcv
6011 hidnplayr 964
        call    socket_ring_read                                ; copy data from kernel buffer to application buffer
965
        call    socket_ring_free                                ; free read memory
4219 hidnplayr 966
        pop     eax
3545 hidnplayr 967
 
7680 hidnplayr 968
        cmp     [eax + STREAM_SOCKET.rcv.size], 0
5364 hidnplayr 969
        jne     .more_data
3704 hidnplayr 970
        xor     ebx, ebx                                        ; errorcode = 0 (no error)
3545 hidnplayr 971
        ret
972
 
5364 hidnplayr 973
  .more_data:
6011 hidnplayr 974
        call    socket_notify                                   ; Queue another network event
5364 hidnplayr 975
        xor     ebx, ebx                                        ; errorcode = 0 (no error)
976
        ret
977
 
3704 hidnplayr 978
  .wouldblock:
979
        push    EWOULDBLOCK
980
        pop     ebx
4219 hidnplayr 981
        xor     ecx, ecx
3704 hidnplayr 982
        ret
983
 
3545 hidnplayr 984
  .peek:
7680 hidnplayr 985
        mov     ecx, [eax + STREAM_SOCKET.rcv.size]
3704 hidnplayr 986
        xor     ebx, ebx
3545 hidnplayr 987
        ret
988
 
989
 
5976 hidnplayr 990
;-----------------------------------------------------------------;
991
;                                                                 ;
6011 hidnplayr 992
; socket_send: Send some data to the remote end.                  ;
5976 hidnplayr 993
;                                                                 ;
994
;   IN: ecx = socket number                                       ;
995
;       edx = pointer to data                                     ;
996
;       esi = data length                                         ;
997
;       edi = flags                                               ;
998
;                                                                 ;
999
;  OUT: eax = number of bytes sent                                ;
1000
;       eax = -1 on error                                         ;
1001
;       ebx = errorcode on error                                  ;
1002
;                                                                 ;
1003
;-----------------------------------------------------------------;
3545 hidnplayr 1004
align 4
6011 hidnplayr 1005
socket_send:
3545 hidnplayr 1006
 
3556 hidnplayr 1007
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: socknum=%u data ptr=%x length=%u flags=%x\n", ecx, edx, esi, edi
3545 hidnplayr 1008
 
6011 hidnplayr 1009
        call    socket_num_to_ptr
5969 hidnplayr 1010
        test    eax, eax
3658 hidnplayr 1011
        jz      .invalid
3545 hidnplayr 1012
 
9049 hidnplayr 1013
        stdcall is_region_userspace, edx, esi
1014
        jnz     .invalid
1015
 
3545 hidnplayr 1016
        mov     ecx, esi
1017
        mov     esi, edx
1018
 
1019
        jmp     [eax + SOCKET.snd_proc]
1020
 
3658 hidnplayr 1021
  .invalid:
9917 Doczom 1022
        mov     dword[esp + SYSCALL_STACK.ebx], EINVAL
1023
        mov     dword[esp + SYSCALL_STACK.eax], -1
3658 hidnplayr 1024
        ret
3545 hidnplayr 1025
 
3658 hidnplayr 1026
 
3545 hidnplayr 1027
align 4
6011 hidnplayr 1028
socket_send_udp:
3545 hidnplayr 1029
 
3556 hidnplayr 1030
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: UDP\n"
3545 hidnplayr 1031
 
9917 Doczom 1032
        mov     [esp + SYSCALL_STACK.eax], ecx
6011 hidnplayr 1033
        call    udp_output
3545 hidnplayr 1034
        cmp     eax, -1
3658 hidnplayr 1035
        je      .error
3545 hidnplayr 1036
        ret
1037
 
3658 hidnplayr 1038
  .error:
9917 Doczom 1039
        mov     dword[esp + SYSCALL_STACK.eax], -1
1040
        mov     dword[esp + SYSCALL_STACK.ebx], EMSGSIZE ; FIXME: UDP_output should return error codes!
3658 hidnplayr 1041
        ret
3545 hidnplayr 1042
 
3658 hidnplayr 1043
 
3545 hidnplayr 1044
align 4
6011 hidnplayr 1045
socket_send_tcp:
3545 hidnplayr 1046
 
3556 hidnplayr 1047
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: TCP\n"
3545 hidnplayr 1048
 
1049
        push    eax
1050
        add     eax, STREAM_SOCKET.snd
6011 hidnplayr 1051
        call    socket_ring_write
3545 hidnplayr 1052
        pop     eax
1053
 
9917 Doczom 1054
        mov     [esp + SYSCALL_STACK.eax], ecx
3658 hidnplayr 1055
        mov     [eax + SOCKET.errorcode], 0
1056
        push    eax
6011 hidnplayr 1057
        call    tcp_output              ; FIXME: this doesnt look pretty, does it?
3658 hidnplayr 1058
        pop     eax
1059
        mov     eax, [eax + SOCKET.errorcode]
9917 Doczom 1060
        mov     [esp + SYSCALL_STACK.ebx], eax
3545 hidnplayr 1061
        ret
1062
 
1063
 
1064
align 4
6011 hidnplayr 1065
socket_send_ip:
3545 hidnplayr 1066
 
3556 hidnplayr 1067
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: IPv4\n"
3545 hidnplayr 1068
 
9917 Doczom 1069
        mov     [esp + SYSCALL_STACK.eax], ecx
6011 hidnplayr 1070
        call    ipv4_output_raw
3545 hidnplayr 1071
        cmp     eax, -1
3658 hidnplayr 1072
        je      .error
3545 hidnplayr 1073
        ret
1074
 
3658 hidnplayr 1075
  .error:
9917 Doczom 1076
        mov     dword[esp + SYSCALL_STACK.eax], eax
1077
        mov     dword[esp + SYSCALL_STACK.ebx], ebx
3658 hidnplayr 1078
        ret
3545 hidnplayr 1079
 
3658 hidnplayr 1080
 
3545 hidnplayr 1081
align 4
6011 hidnplayr 1082
socket_send_icmp:
3545 hidnplayr 1083
 
3556 hidnplayr 1084
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: ICMP\n"
3545 hidnplayr 1085
 
9917 Doczom 1086
        mov     [esp + SYSCALL_STACK.eax], ecx
6011 hidnplayr 1087
        call    icmp_output_raw
3545 hidnplayr 1088
        cmp     eax, -1
3658 hidnplayr 1089
        je      .error
3545 hidnplayr 1090
        ret
1091
 
3658 hidnplayr 1092
  .error:
9917 Doczom 1093
        mov     dword[esp + SYSCALL_STACK.eax], eax
1094
        mov     dword[esp + SYSCALL_STACK.ebx], ebx
3658 hidnplayr 1095
        ret
3545 hidnplayr 1096
 
3658 hidnplayr 1097
 
9049 hidnplayr 1098
;align 4
1099
;socket_send_pppoe:
1100
;
1101
;        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: PPPoE\n"
1102
;
9917 Doczom 1103
;        mov     [esp + SYSCALL_STACK.eax], ecx
9049 hidnplayr 1104
;        mov     ebx, [eax + SOCKET.device]
1105
;
1106
;        call    pppoe_discovery_output  ; FIXME: errorcodes
1107
;        cmp     eax, -1
1108
;        je      .error
1109
;        ret
1110
;
1111
;  .error:
9917 Doczom 1112
;        mov     dword[esp + SYSCALL_STACK.eax], -1
1113
;        mov     dword[esp + SYSCALL_STACK.ebx], EMSGSIZE
9049 hidnplayr 1114
;        ret
3545 hidnplayr 1115
 
1116
 
1117
 
1118
align 4
6011 hidnplayr 1119
socket_send_local:
3545 hidnplayr 1120
 
1121
        ; does this socket have a PID yet?
1122
        cmp     [eax + SOCKET.PID], 0
1123
        jne     @f
1124
 
1125
        ; Change PID to that of current process
9692 Doczom 1126
        mov     ebx, [current_slot]
1127
        mov     ebx, [ebx + APPDATA.tid]
3545 hidnplayr 1128
        mov     [eax + SOCKET.PID], ebx
1129
        mov     [eax + SOCKET.TID], ebx         ; currently TID = PID in kolibrios :(
1130
      @@:
6011 hidnplayr 1131
        mov     [eax + SOCKET.snd_proc], socket_send_local_initialized
3545 hidnplayr 1132
 
1133
align 4
6011 hidnplayr 1134
socket_send_local_initialized:
3545 hidnplayr 1135
 
3556 hidnplayr 1136
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_send: LOCAL\n"
3545 hidnplayr 1137
 
1138
        ; get the other side's socket and check if it still exists
1139
        mov     eax, [eax + SOCKET.device]
6011 hidnplayr 1140
        call    socket_check
3658 hidnplayr 1141
        jz      .invalid
3545 hidnplayr 1142
 
1143
        ; allright, shove in the data!
1144
        push    eax
1145
        add     eax, STREAM_SOCKET.rcv
6011 hidnplayr 1146
        call    socket_ring_write
3545 hidnplayr 1147
        pop     eax
1148
 
1149
        ; return the number of written bytes (or errorcode) to application
9917 Doczom 1150
        mov     [esp + SYSCALL_STACK.eax], ecx
3545 hidnplayr 1151
 
1152
        ; and notify the other end
6011 hidnplayr 1153
        call    socket_notify
3545 hidnplayr 1154
 
1155
        ret
1156
 
3658 hidnplayr 1157
  .invalid:
9917 Doczom 1158
        mov     dword[esp + SYSCALL_STACK.eax], -1
1159
        mov     dword[esp + SYSCALL_STACK.ebx], EINVAL
3658 hidnplayr 1160
        ret
3545 hidnplayr 1161
 
3658 hidnplayr 1162
 
5976 hidnplayr 1163
;-----------------------------------------------------------------;
1164
;                                                                 ;
6011 hidnplayr 1165
; socket_get_opt: Read a socket option                            ;
5976 hidnplayr 1166
;                                                                 ;
1167
;   IN: ecx = socket number                                       ;
1168
;       edx = pointer to socket options struct                    ;
1169
;                                                                 ;
1170
;  OUT: eax = 0 on success                                        ;
1171
;       eax = -1 on error                                         ;
1172
;       ebx = errorcode on error                                  ;
1173
;                                                                 ;
1174
;-----------------------------------------------------------------;
1175
align 4
6011 hidnplayr 1176
socket_get_opt:
5976 hidnplayr 1177
 
1178
; FIXME:
3545 hidnplayr 1179
; At moment, uses only pseudo-optname -2 for get last_ack_number for TCP.
1180
; TODO: find best way to notify that send()'ed data were acknowledged
1181
; Also pseudo-optname -3 is valid and returns socket state, one of TCPS_*.
1182
 
3556 hidnplayr 1183
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_get_opt\n"
3545 hidnplayr 1184
 
6011 hidnplayr 1185
        call    socket_num_to_ptr
5969 hidnplayr 1186
        test    eax, eax
3658 hidnplayr 1187
        jz      .invalid
3545 hidnplayr 1188
 
1189
        cmp     dword [edx], IP_PROTO_TCP
3658 hidnplayr 1190
        jne     .invalid
3545 hidnplayr 1191
        cmp     dword [edx+4], -2
1192
        je      @f
1193
        cmp     dword [edx+4], -3
3658 hidnplayr 1194
        jne     .invalid
3545 hidnplayr 1195
@@:
1196
;        mov     eax, [edx+12]
1197
;        test    eax, eax
1198
;        jz      .fail
1199
;        cmp     dword [eax], 4
1200
;        mov     dword [eax], 4
1201
;        jb      .fail
1202
;        stdcall net_socket_num_to_addr, ecx
1203
;        test    eax, eax
1204
;        jz      .fail
1205
;        ; todo: check that eax is really TCP socket
1206
;        mov     ecx, [eax + TCP_SOCKET.last_ack_number]
1207
;        cmp     dword [edx+4], -2
1208
;        jz      @f
1209
;        mov     ecx, [eax + TCP_SOCKET.state]
1210
@@:
1211
        mov     eax, [edx+8]
1212
        test    eax, eax
1213
        jz      @f
1214
        mov     [eax], ecx
1215
@@:
9917 Doczom 1216
        mov     dword [esp + SYSCALL_STACK.eax], 0
3545 hidnplayr 1217
        ret
1218
 
3658 hidnplayr 1219
  .invalid:
9917 Doczom 1220
        mov     dword[esp + SYSCALL_STACK.eax], -1
1221
        mov     dword[esp + SYSCALL_STACK.ebx], EINVAL
3658 hidnplayr 1222
        ret
3545 hidnplayr 1223
 
1224
 
5976 hidnplayr 1225
;-----------------------------------------------------------------;
1226
;                                                                 ;
6011 hidnplayr 1227
; socket_set_options: Set a socket option.                        ;
5976 hidnplayr 1228
;                                                                 ;
1229
;   IN: ecx = socket number                                       ;
1230
;       edx = pointer to socket options struct                    ;
1231
;                                                                 ;
1232
;  OUT: eax = 0 on success                                        ;
1233
;       eax = -1 on error                                         ;
1234
;       ebx = errorcode on error                                  ;
1235
;                                                                 ;
1236
;-----------------------------------------------------------------;
3545 hidnplayr 1237
align 4
6011 hidnplayr 1238
socket_set_opt:
3545 hidnplayr 1239
 
3556 hidnplayr 1240
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_set_opt\n"
3545 hidnplayr 1241
 
6011 hidnplayr 1242
        call    socket_num_to_ptr
5969 hidnplayr 1243
        test    eax, eax
3658 hidnplayr 1244
        jz      .invalid
3545 hidnplayr 1245
 
5842 hidnplayr 1246
        cmp     [edx + socket_options.level], IP_PROTO_IP
1247
        je      .ip
1248
        cmp     [edx + socket_options.level], SOL_SOCKET
3658 hidnplayr 1249
        jne     .invalid
3545 hidnplayr 1250
 
5842 hidnplayr 1251
  .socket:
1252
        cmp     [edx + socket_options.optname], SO_BINDTODEVICE
1253
        jne     .invalid
3545 hidnplayr 1254
 
1255
  .bind:
5842 hidnplayr 1256
        cmp     [edx + socket_options.optlen], 0
3545 hidnplayr 1257
        je      .unbind
1258
 
5842 hidnplayr 1259
        movzx   edx, byte[edx + socket_options.optval]
3600 hidnplayr 1260
        cmp     edx, NET_DEVICES_MAX
3658 hidnplayr 1261
        ja      .invalid
3545 hidnplayr 1262
 
7679 hidnplayr 1263
        mov     edx, [net_device_list + 4*edx]
3545 hidnplayr 1264
        test    edx, edx
3658 hidnplayr 1265
        jz      .already
3545 hidnplayr 1266
        mov     [eax + SOCKET.device], edx
1267
 
5584 hidnplayr 1268
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_set_opt: Bound socket %x to device %x\n", eax, edx
3545 hidnplayr 1269
 
9917 Doczom 1270
        mov     dword[esp + SYSCALL_STACK.eax], 0        ; success!
3545 hidnplayr 1271
        ret
1272
 
1273
  .unbind:
1274
        mov     [eax + SOCKET.device], 0
1275
 
9917 Doczom 1276
        mov     dword[esp + SYSCALL_STACK.eax], 0        ; success!
3545 hidnplayr 1277
        ret
1278
 
5842 hidnplayr 1279
  .ip:
1280
        cmp     [edx + socket_options.optname], IP_TTL
1281
        jne     .invalid
1282
 
1283
  .ttl:
1284
        mov     bl, byte[edx + socket_options.optval]
1285
        mov     [eax + IP_SOCKET.ttl], bl
1286
 
9917 Doczom 1287
        mov     dword[esp + SYSCALL_STACK.eax], 0        ; success!
5842 hidnplayr 1288
        ret
1289
 
3658 hidnplayr 1290
  .already:
9917 Doczom 1291
        mov     dword[esp + SYSCALL_STACK.ebx], EALREADY
1292
        mov     dword[esp + SYSCALL_STACK.eax], -1
3658 hidnplayr 1293
        ret
3545 hidnplayr 1294
 
5842 hidnplayr 1295
  .invalid:
9917 Doczom 1296
        mov     dword[esp + SYSCALL_STACK.ebx], EINVAL
1297
        mov     dword[esp + SYSCALL_STACK.eax], -1
5842 hidnplayr 1298
        ret
3545 hidnplayr 1299
 
3658 hidnplayr 1300
 
1301
 
5842 hidnplayr 1302
 
5976 hidnplayr 1303
;-----------------------------------------------------------------;
1304
;                                                                 ;
6011 hidnplayr 1305
; socket_pair: Allocate a pair of linked local sockets.           ;
5976 hidnplayr 1306
;                                                                 ;
1307
;  IN: /                                                          ;
1308
;                                                                 ;
1309
; OUT: eax = socket1 num on success                               ;
1310
;      eax = -1 on error                                          ;
1311
;      ebx = socket2 num on success                               ;
1312
;      ebx = errorcode on error                                   ;
1313
;                                                                 ;
1314
;-----------------------------------------------------------------;
3545 hidnplayr 1315
align 4
6011 hidnplayr 1316
socket_pair:
3545 hidnplayr 1317
 
3556 hidnplayr 1318
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_pair\n"
3545 hidnplayr 1319
 
6011 hidnplayr 1320
        call    socket_alloc
4535 hidnplayr 1321
        test    eax, eax
3658 hidnplayr 1322
        jz      .nomem1
9917 Doczom 1323
        mov     [esp + SYSCALL_STACK.eax], edi   ; application's eax
3545 hidnplayr 1324
 
1325
        mov     [eax + SOCKET.Domain], AF_LOCAL
1326
        mov     [eax + SOCKET.Type], SOCK_STREAM
1327
        mov     [eax + SOCKET.Protocol], 0              ;;; CHECKME
6011 hidnplayr 1328
        mov     [eax + SOCKET.snd_proc], socket_send_local
1329
        mov     [eax + SOCKET.rcv_proc], socket_receive_local
3545 hidnplayr 1330
        mov     [eax + SOCKET.PID], 0
1331
        mov     ebx, eax
1332
 
6011 hidnplayr 1333
        call    socket_alloc
4535 hidnplayr 1334
        test    eax, eax
3658 hidnplayr 1335
        jz      .nomem2
9917 Doczom 1336
        mov     [esp + SYSCALL_STACK.ebx], edi   ; application's ebx
3545 hidnplayr 1337
 
1338
        mov     [eax + SOCKET.Domain], AF_LOCAL
1339
        mov     [eax + SOCKET.Type], SOCK_STREAM
1340
        mov     [eax + SOCKET.Protocol], 0              ;;; CHECKME
6011 hidnplayr 1341
        mov     [eax + SOCKET.snd_proc], socket_send_local
1342
        mov     [eax + SOCKET.rcv_proc], socket_receive_local
3545 hidnplayr 1343
        mov     [eax + SOCKET.PID], 0
1344
 
1345
        ; Link the two sockets to eachother
1346
        mov     [eax + SOCKET.device], ebx
1347
        mov     [ebx + SOCKET.device], eax
1348
 
1349
        lea     eax, [eax + STREAM_SOCKET.rcv]
6011 hidnplayr 1350
        call    socket_ring_create
5155 hidnplayr 1351
        test    eax, eax
5969 hidnplayr 1352
        jz      .nomem2
3545 hidnplayr 1353
 
1354
        lea     eax, [ebx + STREAM_SOCKET.rcv]
6011 hidnplayr 1355
        call    socket_ring_create
5155 hidnplayr 1356
        test    eax, eax
1357
        jz      .nomem2
3545 hidnplayr 1358
 
1359
        ret
1360
 
3658 hidnplayr 1361
  .nomem2:
9917 Doczom 1362
        mov     eax, [esp + SYSCALL_STACK.ebx]
6011 hidnplayr 1363
        call    socket_free
5969 hidnplayr 1364
 
3658 hidnplayr 1365
  .nomem1:
9917 Doczom 1366
        mov     eax, [esp + SYSCALL_STACK.eax]
6011 hidnplayr 1367
        call    socket_free
5969 hidnplayr 1368
 
9917 Doczom 1369
        mov     dword[esp + SYSCALL_STACK.eax], -1
1370
        mov     dword[esp + SYSCALL_STACK.ebx], ENOMEM
3658 hidnplayr 1371
        ret
3545 hidnplayr 1372
 
1373
 
1374
 
5976 hidnplayr 1375
;-----------------------------------------------------------------;
1376
;                                                                 ;
6011 hidnplayr 1377
; socket_debug: Copy socket variables to application buffer.      ;
5976 hidnplayr 1378
;                                                                 ;
1379
;   IN: ecx = socket number                                       ;
1380
;       edx = pointer to application buffer                       ;
1381
;                                                                 ;
1382
;  OUT: eax = 0 on success                                        ;
1383
;       eax = -1 on error                                         ;
1384
;       ebx = errorcode on error                                  ;
1385
;                                                                 ;
1386
;-----------------------------------------------------------------;
3545 hidnplayr 1387
align 4
6011 hidnplayr 1388
socket_debug:
3545 hidnplayr 1389
 
3556 hidnplayr 1390
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_debug\n"
3545 hidnplayr 1391
 
1392
        mov     edi, edx
1393
 
1394
        test    ecx, ecx
1395
        jz      .returnall
1396
 
6011 hidnplayr 1397
        call    socket_num_to_ptr
5969 hidnplayr 1398
        test    eax, eax
3658 hidnplayr 1399
        jz      .invalid
3545 hidnplayr 1400
 
9049 hidnplayr 1401
        stdcall is_region_userspace, edi, SOCKET_STRUCT_SIZE
1402
        jnz     .invalid
1403
 
3545 hidnplayr 1404
        mov     esi, eax
6413 hidnplayr 1405
        mov     ecx, SOCKET_STRUCT_SIZE/4
3711 clevermous 1406
        rep movsd
3545 hidnplayr 1407
 
3658 hidnplayr 1408
        mov     dword[esp+32], 0
3545 hidnplayr 1409
        ret
1410
 
1411
  .returnall:
1412
        mov     ebx, net_sockets
1413
  .next_socket:
1414
        mov     ebx, [ebx + SOCKET.NextPtr]
1415
        test    ebx, ebx
1416
        jz      .done
1417
        mov     eax, [ebx + SOCKET.Number]
1418
        stosd
1419
        jmp     .next_socket
1420
  .done:
1421
        xor     eax, eax
1422
        stosd
9917 Doczom 1423
        mov     dword[esp + SYSCALL_STACK.eax], eax
3658 hidnplayr 1424
        ret
3545 hidnplayr 1425
 
3658 hidnplayr 1426
  .invalid:
9917 Doczom 1427
        mov     dword[esp + SYSCALL_STACK.eax], -1
1428
        mov     dword[esp + SYSCALL_STACK.ebx], EINVAL
3545 hidnplayr 1429
        ret
1430
 
1431
 
5976 hidnplayr 1432
;-----------------------------------------------------------------;
1433
;   ____                                                 ____     ;
1434
;   \  /              End of sockets API                 \  /     ;
1435
;    \/                                                   \/      ;
1436
;    ()        Internally used functions follow           ()      ;
1437
;                                                                 ;
1438
;-----------------------------------------------------------------;
1439
 
1440
 
1441
;-----------------------------------------------------------------;
1442
;                                                                 ;
6011 hidnplayr 1443
; socket_find_port:                                               ;
5976 hidnplayr 1444
; Fill in the local port number for TCP and UDP sockets           ;
1445
; This procedure always works because the number of sockets is    ;
1446
; limited to a smaller number then the number of possible ports   ;
1447
;                                                                 ;
1448
;  IN:  eax = socket pointer                                      ;
1449
;                                                                 ;
1450
;  OUT: /                                                         ;
1451
;                                                                 ;
1452
;-----------------------------------------------------------------;
3545 hidnplayr 1453
align 4
6011 hidnplayr 1454
socket_find_port:
3545 hidnplayr 1455
 
3556 hidnplayr 1456
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_find_port\n"
3545 hidnplayr 1457
 
1458
        push    ebx esi ecx
1459
 
1460
        cmp     [eax + SOCKET.Protocol], IP_PROTO_UDP
1461
        je      .udp
1462
 
1463
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
1464
        je      .tcp
1465
 
1466
        pop     ecx esi ebx
1467
        ret
1468
 
1469
  .udp:
1470
        mov     bx, [last_UDP_port]
1471
        call    .findit
1472
        mov     [last_UDP_port], bx
1473
 
1474
        pop     ecx esi ebx
1475
        ret
1476
 
1477
  .tcp:
1478
        mov     bx, [last_TCP_port]
1479
        call    .findit
1480
        mov     [last_TCP_port], bx
1481
 
1482
        pop     ecx esi ebx
1483
        ret
1484
 
1485
 
1486
  .restart:
1487
        mov     bx, MIN_EPHEMERAL_PORT_N
1488
  .findit:
1489
        cmp     bx, MAX_EPHEMERAL_PORT_N
1490
        je      .restart
1491
 
1492
        add     bh, 1
1493
        adc     bl, 0
1494
 
6011 hidnplayr 1495
        call    socket_check_port
3545 hidnplayr 1496
        jz      .findit
1497
        ret
1498
 
1499
 
1500
 
5976 hidnplayr 1501
;-----------------------------------------------------------------;
1502
;                                                                 ;
6011 hidnplayr 1503
; socket_check_port: (to be used with AF_INET only!)              ;
5976 hidnplayr 1504
; Checks if a local port number is unused                         ;
1505
; If the proposed port number is unused, it is filled in in the   ;
6011 hidnplayr 1506
; socket structure.                                               ;
5976 hidnplayr 1507
;                                                                 ;
1508
;   IN: eax = socket ptr                                          ;
1509
;       bx = proposed socket number (network byte order)          ;
1510
;                                                                 ;
1511
;  OUT: ZF = set on error                                         ;
1512
;                                                                 ;
1513
;-----------------------------------------------------------------;
3545 hidnplayr 1514
align 4
6011 hidnplayr 1515
socket_check_port:
3545 hidnplayr 1516
 
3556 hidnplayr 1517
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_check_port: "
3545 hidnplayr 1518
 
3647 hidnplayr 1519
        pusha
1520
        mov     ecx, socket_mutex
1521
        call    mutex_lock
1522
        popa
1523
 
3545 hidnplayr 1524
        mov     ecx, [eax + SOCKET.Protocol]
1525
        mov     edx, [eax + IP_SOCKET.LocalIP]
1526
        mov     esi, net_sockets
1527
 
1528
  .next_socket:
1529
        mov     esi, [esi + SOCKET.NextPtr]
1530
        or      esi, esi
1531
        jz      .port_ok
1532
 
1533
        cmp     [esi + SOCKET.Protocol], ecx
1534
        jne     .next_socket
1535
 
1536
        cmp     [esi + IP_SOCKET.LocalIP], edx
1537
        jne     .next_socket
1538
 
1539
        cmp     [esi + UDP_SOCKET.LocalPort], bx
1540
        jne     .next_socket
1541
 
3647 hidnplayr 1542
        pusha
1543
        mov     ecx, socket_mutex
1544
        call    mutex_unlock
1545
        popa
1546
 
3556 hidnplayr 1547
        DEBUGF  DEBUG_NETWORK_VERBOSE, "local port %x already in use\n", bx  ; FIXME: find a way to print big endian values with debugf
3545 hidnplayr 1548
        ret
1549
 
1550
  .port_ok:
3647 hidnplayr 1551
        pusha
1552
        mov     ecx, socket_mutex
1553
        call    mutex_unlock
1554
        popa
1555
 
3556 hidnplayr 1556
        DEBUGF  DEBUG_NETWORK_VERBOSE, "local port %x is free\n", bx         ; FIXME: find a way to print big endian values with debugf
3545 hidnplayr 1557
        mov     [eax + UDP_SOCKET.LocalPort], bx
1558
        or      bx, bx                                  ; clear the zero-flag
1559
        ret
1560
 
1561
 
1562
 
5976 hidnplayr 1563
;-----------------------------------------------------------------;
1564
;                                                                 ;
6011 hidnplayr 1565
; socket_input: Update a (stateless) socket with received data.   ;
5976 hidnplayr 1566
;                                                                 ;
1567
; Note: The socket's mutex should already be set !                ;
1568
;                                                                 ;
1569
;   IN: eax = socket ptr                                          ;
1570
;       ecx = data size                                           ;
1571
;       esi = ptr to data                                         ;
1572
;       [esp] = ptr to buf                                        ;
1573
;                                                                 ;
1574
;  OUT: /                                                         ;
1575
;                                                                 ;
1576
;-----------------------------------------------------------------;
3545 hidnplayr 1577
align 4
6011 hidnplayr 1578
socket_input:
3545 hidnplayr 1579
 
3556 hidnplayr 1580
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_input: socket=%x, data=%x size=%u\n", eax, esi, ecx
3545 hidnplayr 1581
 
5522 hidnplayr 1582
        push    ecx
3545 hidnplayr 1583
        push    esi
1584
        mov     esi, esp
1585
 
6011 hidnplayr 1586
        add_to_queue (eax + SOCKET_QUEUE_LOCATION), SOCKET_QUEUE_SIZE, sizeof.socket_queue_entry, .full
3545 hidnplayr 1587
 
3556 hidnplayr 1588
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_input: success\n"
3545 hidnplayr 1589
        add     esp, sizeof.socket_queue_entry
1590
 
1591
        pusha
1592
        lea     ecx, [eax + SOCKET.mutex]
1593
        call    mutex_unlock
1594
        popa
1595
 
6011 hidnplayr 1596
        jmp     socket_notify
3545 hidnplayr 1597
 
1598
  .full:
7680 hidnplayr 1599
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_input: socket %x is full!\n", eax
3545 hidnplayr 1600
 
1601
        pusha
1602
        lea     ecx, [eax + SOCKET.mutex]
1603
        call    mutex_unlock
1604
        popa
1605
 
5842 hidnplayr 1606
        add     esp, 8
6011 hidnplayr 1607
        call    net_buff_free
3545 hidnplayr 1608
        ret
1609
 
1610
 
5976 hidnplayr 1611
;-----------------------------------------------------------------;
1612
;                                                                 ;
6011 hidnplayr 1613
; socket_ring_create: Create a ringbuffer for sockets.            ;
5976 hidnplayr 1614
;                                                                 ;
1615
;   IN: eax = ptr to ring struct                                  ;
1616
;                                                                 ;
1617
;  OUT: eax = 0 on error                                          ;
1618
;       eax = start ptr                                           ;
1619
;                                                                 ;
1620
;-----------------------------------------------------------------;
3545 hidnplayr 1621
align 4
6011 hidnplayr 1622
socket_ring_create:
3545 hidnplayr 1623
 
1624
        push    esi
1625
        mov     esi, eax
1626
 
1627
        push    edx
6413 hidnplayr 1628
        stdcall create_ring_buffer, SOCKET_BUFFER_SIZE, PG_SWR
3545 hidnplayr 1629
        pop     edx
5155 hidnplayr 1630
        test    eax, eax
1631
        jz      .fail
3545 hidnplayr 1632
 
5969 hidnplayr 1633
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_create: %x\n", eax
3545 hidnplayr 1634
 
1635
        pusha
1636
        lea     ecx, [esi + RING_BUFFER.mutex]
1637
        call    mutex_init
1638
        popa
1639
 
1640
        mov     [esi + RING_BUFFER.start_ptr], eax
1641
        mov     [esi + RING_BUFFER.write_ptr], eax
1642
        mov     [esi + RING_BUFFER.read_ptr], eax
1643
        mov     [esi + RING_BUFFER.size], 0
6413 hidnplayr 1644
        add     eax, SOCKET_BUFFER_SIZE
3545 hidnplayr 1645
        mov     [esi + RING_BUFFER.end_ptr], eax
1646
        mov     eax, esi
1647
 
5969 hidnplayr 1648
        pop     esi
1649
        ret
1650
 
5155 hidnplayr 1651
  .fail:
5969 hidnplayr 1652
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_ring_create: Out of memory!\n"
5566 hidnplayr 1653
        pop     esi
3545 hidnplayr 1654
        ret
1655
 
5976 hidnplayr 1656
;-----------------------------------------------------------------;
1657
;                                                                 ;
6011 hidnplayr 1658
; socket_ring_write: Write data to ring buffer.                   ;
5976 hidnplayr 1659
;                                                                 ;
1660
;   IN: eax = ptr to ring struct                                  ;
1661
;       ecx = data size                                           ;
1662
;       esi = ptr to data                                         ;
1663
;                                                                 ;
1664
;  OUT: ecx = number of bytes stored                              ;
1665
;                                                                 ;
1666
;-----------------------------------------------------------------;
3545 hidnplayr 1667
align 4
6011 hidnplayr 1668
socket_ring_write:
3545 hidnplayr 1669
 
3556 hidnplayr 1670
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_write: ringbuff=%x ptr=%x size=%u\n", eax, esi, ecx
3545 hidnplayr 1671
 
1672
; lock mutex
1673
        pusha
1674
        lea     ecx, [eax + RING_BUFFER.mutex]
1675
        call    mutex_lock                                      ; TODO: check what registers this function actually destroys
1676
        popa
1677
 
1678
; calculate available size
6413 hidnplayr 1679
        mov     edi, SOCKET_BUFFER_SIZE
3545 hidnplayr 1680
        sub     edi, [eax + RING_BUFFER.size]                   ; available buffer size in edi
1681
        cmp     ecx, edi
1682
        jbe     .copy
1683
        mov     ecx, edi
1684
  .copy:
1685
        mov     edi, [eax + RING_BUFFER.write_ptr]
3556 hidnplayr 1686
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_write: %u bytes from %x to %x\n", ecx, esi, edi
3545 hidnplayr 1687
 
1688
; update write ptr
1689
        push    edi
1690
        add     edi, ecx
1691
        cmp     edi, [eax + RING_BUFFER.end_ptr]
1692
        jb      @f
6413 hidnplayr 1693
        sub     edi, SOCKET_BUFFER_SIZE                         ; WRAP
3545 hidnplayr 1694
  @@:
1695
        mov     [eax + RING_BUFFER.write_ptr], edi
1696
        pop     edi
1697
 
1698
; update size
1699
        add     [eax + RING_BUFFER.size], ecx
1700
 
1701
; copy the data
1702
        push    ecx
1703
        shr     ecx, 1
1704
        jnc     .nb
1705
        movsb
1706
  .nb:
1707
        shr     ecx, 1
1708
        jnc     .nw
1709
        movsw
1710
  .nw:
1711
        test    ecx, ecx
1712
        jz      .nd
3711 clevermous 1713
        rep movsd
3545 hidnplayr 1714
  .nd:
1715
        pop     ecx
1716
 
1717
; unlock mutex
4344 hidnplayr 1718
        pusha
3545 hidnplayr 1719
        lea     ecx, [eax + RING_BUFFER.mutex]
1720
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
4344 hidnplayr 1721
        popa
3545 hidnplayr 1722
 
1723
        ret
1724
 
5976 hidnplayr 1725
;-----------------------------------------------------------------;
1726
;                                                                 ;
6011 hidnplayr 1727
; socket_ring_read: Read from ring buffer                         ;
5976 hidnplayr 1728
;                                                                 ;
1729
;   IN: eax = ring struct ptr                                     ;
1730
;       ecx = bytes to read                                       ;
1731
;       edx = offset                                              ;
1732
;       edi = ptr to buffer start                                 ;
1733
;                                                                 ;
1734
;  OUT: eax = unchanged                                           ;
1735
;       ecx = number of bytes read (0 on error)                   ;
1736
;       edx = destroyed                                           ;
1737
;       esi = destroyed                                           ;
1738
;       edi = ptr to buffer end                                   ;
1739
;                                                                 ;
1740
;-----------------------------------------------------------------;
3545 hidnplayr 1741
align 4
6011 hidnplayr 1742
socket_ring_read:
3545 hidnplayr 1743
 
3556 hidnplayr 1744
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: ringbuff=%x ptr=%x size=%u offset=%x\n", eax, edi, ecx, edx
3545 hidnplayr 1745
 
1746
        pusha
1747
        lea     ecx, [eax + RING_BUFFER.mutex]
1748
        call    mutex_lock                                      ; TODO: check what registers this function actually destroys
1749
        popa
1750
 
1751
        mov     esi, [eax + RING_BUFFER.read_ptr]
1752
        add     esi, edx                                        ; esi = start_ptr + offset
1753
 
1754
        neg     edx
1755
        add     edx, [eax + RING_BUFFER.size]                   ; edx = snd.size - offset
1756
        jle     .no_data_at_all
1757
 
1758
        pusha
1759
        lea     ecx, [eax + RING_BUFFER.mutex]
1760
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
1761
        popa
1762
 
1763
        cmp     ecx, edx
1764
        ja      .less_data
1765
 
1766
  .copy:
3556 hidnplayr 1767
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_read: %u bytes from %x to %x\n", ecx, esi, edi
3545 hidnplayr 1768
        push    ecx
1769
        shr     ecx, 1
1770
        jnc     .nb
1771
        movsb
1772
  .nb:
1773
        shr     ecx, 1
1774
        jnc     .nw
1775
        movsw
1776
  .nw:
1777
        test    ecx, ecx
1778
        jz      .nd
3711 clevermous 1779
        rep movsd
3545 hidnplayr 1780
  .nd:
1781
        pop     ecx
1782
        ret
1783
 
1784
  .no_data_at_all:
1785
        pusha
1786
        lea     ecx, [eax + RING_BUFFER.mutex]
1787
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
1788
        popa
1789
 
7680 hidnplayr 1790
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_ring_read: no data at all!\n"
3545 hidnplayr 1791
        xor     ecx, ecx
1792
        ret
1793
 
1794
  .less_data:
1795
        mov     ecx, edx
1796
        jmp     .copy
1797
 
1798
 
5976 hidnplayr 1799
;-----------------------------------------------------------------;
1800
;                                                                 ;
6011 hidnplayr 1801
; socket_ring_free: Free data from a ringbuffer.                  ;
5976 hidnplayr 1802
;                                                                 ;
1803
;   IN: eax = ptr to ring struct                                  ;
1804
;       ecx = data size                                           ;
1805
;                                                                 ;
1806
;  OUT: ecx = number of freed bytes                               ;
1807
;                                                                 ;
1808
;-----------------------------------------------------------------;
3545 hidnplayr 1809
align 4
6011 hidnplayr 1810
socket_ring_free:
3545 hidnplayr 1811
 
3556 hidnplayr 1812
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ring_free: %u bytes from ring %x\n", ecx, eax
3545 hidnplayr 1813
 
1814
        push    eax ecx
1815
        lea     ecx, [eax + RING_BUFFER.mutex]
1816
        call    mutex_lock                                      ; TODO: check what registers this function actually destroys
1817
        pop     ecx eax
1818
 
1819
        sub     [eax + RING_BUFFER.size], ecx
1820
        jb      .error
1821
        add     [eax + RING_BUFFER.read_ptr], ecx
1822
 
1823
        mov     edx, [eax + RING_BUFFER.end_ptr]
1824
        cmp     [eax + RING_BUFFER.read_ptr], edx
1825
        jb      @f
6413 hidnplayr 1826
        sub     [eax + RING_BUFFER.read_ptr], SOCKET_BUFFER_SIZE
3545 hidnplayr 1827
       @@:
1828
 
1829
        push    eax ecx
1830
        lea     ecx, [eax + RING_BUFFER.mutex]                  ; TODO: check what registers this function actually destroys
1831
        call    mutex_unlock
1832
        pop     ecx eax
1833
 
1834
        ret
1835
 
1836
  .error:       ; we could free all available bytes, but that would be stupid, i guess..
7680 hidnplayr 1837
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_ring_free: buffer=%x error!\n", eax
3545 hidnplayr 1838
        add     [eax + RING_BUFFER.size], ecx
1839
 
1840
        push    eax
1841
        lea     ecx, [eax + RING_BUFFER.mutex]
1842
        call    mutex_unlock                                    ; TODO: check what registers this function actually destroys
1843
        pop     eax
1844
 
1845
        xor     ecx, ecx
1846
        ret
1847
 
1848
 
5976 hidnplayr 1849
;-----------------------------------------------------------------;
1850
;                                                                 ;
6011 hidnplayr 1851
; socket_block: Suspend the thread attached to a socket.          ;
5976 hidnplayr 1852
;                                                                 ;
1853
;   IN: eax = socket ptr                                          ;
1854
;                                                                 ;
1855
;  OUT: eax = unchanged                                           ;
1856
;                                                                 ;
1857
;-----------------------------------------------------------------;
3545 hidnplayr 1858
align 4
6011 hidnplayr 1859
socket_block:
3545 hidnplayr 1860
 
6908 ashmew2 1861
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_block: %x\n", eax
3545 hidnplayr 1862
 
4520 hidnplayr 1863
        push    eax
1864
 
3545 hidnplayr 1865
        pushf
1866
        cli
1867
        ; Set the 'socket is blocked' flag
1868
        or      [eax + SOCKET.state], SS_BLOCKED
1869
 
1870
        ; Suspend the thread
1871
        push    edx
9692 Doczom 1872
        mov     edx, [current_slot]
9709 Doczom 1873
        mov     [edx + APPDATA.state], TSTATE_RUN_SUSPENDED
3545 hidnplayr 1874
 
1875
        ; Remember the thread ID so we can wake it up again
9692 Doczom 1876
        mov     edx, [edx + APPDATA.tid]
3556 hidnplayr 1877
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_block: suspending thread: %u\n", edx
3545 hidnplayr 1878
        mov     [eax + SOCKET.TID], edx
1879
        pop     edx
4520 hidnplayr 1880
        popf
3545 hidnplayr 1881
 
1882
        call    change_task
3674 hidnplayr 1883
        pop     eax
3545 hidnplayr 1884
 
6908 ashmew2 1885
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_block: continuing\n"
3545 hidnplayr 1886
 
1887
        ret
1888
 
1889
 
5976 hidnplayr 1890
;-----------------------------------------------------------------;
1891
;                                                                 ;
6011 hidnplayr 1892
; socket_notify: Wake up socket owner thread.                     ;
5976 hidnplayr 1893
;                                                                 ;
1894
;   IN: eax = socket ptr                                          ;
1895
;                                                                 ;
1896
;  OUT: eax = unchanged                                           ;
1897
;                                                                 ;
1898
;-----------------------------------------------------------------;
3545 hidnplayr 1899
align 4
6011 hidnplayr 1900
socket_notify:
3545 hidnplayr 1901
 
3556 hidnplayr 1902
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_notify: %x\n", eax
3545 hidnplayr 1903
 
6011 hidnplayr 1904
        call    socket_check
3545 hidnplayr 1905
        jz      .error
1906
 
9917 Doczom 1907
; Find the associated thread's
4527 hidnplayr 1908
        push    ebx ecx esi
1909
        mov     ebx, [eax + SOCKET.TID]
1910
        test    ebx, ebx
1911
        jz      .error2
1912
        xor     ecx, ecx
3545 hidnplayr 1913
        inc     ecx
9692 Doczom 1914
        mov     esi, SLOT_BASE + sizeof.APPDATA
4527 hidnplayr 1915
  .next:
9692 Doczom 1916
        cmp     [esi + APPDATA.tid], ebx
4527 hidnplayr 1917
        je      .found
1918
        inc     ecx
9692 Doczom 1919
        add     esi, sizeof.APPDATA
8866 rgimad 1920
        cmp     ecx, [thread_count]
4527 hidnplayr 1921
        jbe     .next
1922
 
1923
  .error2:
3545 hidnplayr 1924
; PID not found, TODO: close socket!
4527 hidnplayr 1925
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_notify: error finding thread 0x%x !\n", ebx
1926
        pop     esi ecx ebx
1927
        ret
3545 hidnplayr 1928
 
4527 hidnplayr 1929
  .error:
4528 hidnplayr 1930
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_notify: invalid socket ptr: 0x%x !\n", eax
4527 hidnplayr 1931
        ret
1932
 
1933
  .found:
1934
        test    [eax + SOCKET.state], SS_BLOCKED
4528 hidnplayr 1935
        jnz     .un_block
4527 hidnplayr 1936
 
5976 hidnplayr 1937
; Socket and thread exists and socket is of non blocking type.
4527 hidnplayr 1938
; We'll try to flag an event to the thread.
9917 Doczom 1939
        or      [esi + APPDATA.occurred_events], EVENT_NETWORK
3545 hidnplayr 1940
 
6413 hidnplayr 1941
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_notify: poking thread %u!\n", ebx
4527 hidnplayr 1942
        pop     esi ecx ebx
1943
        ret
3545 hidnplayr 1944
 
4527 hidnplayr 1945
 
4528 hidnplayr 1946
  .un_block:
5976 hidnplayr 1947
; Socket and thread exists and socket is of blocking type
4527 hidnplayr 1948
; We'll try to unblock it.
1949
        and     [eax + SOCKET.state], not SS_BLOCKED    ; Clear the 'socket is blocked' flag
9917 Doczom 1950
        mov     [esi + APPDATA.state], TSTATE_RUNNING  ; Run the thread
3545 hidnplayr 1951
 
6908 ashmew2 1952
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_notify: Unblocked socket!\n"
4527 hidnplayr 1953
        pop     esi ecx ebx
3545 hidnplayr 1954
        ret
1955
 
1956
 
5976 hidnplayr 1957
;-----------------------------------------------------------------;
1958
;                                                                 ;
6011 hidnplayr 1959
; socket_alloc: Allocate memory for socket and put new socket     ;
1960
; into the list. Newly created socket is initialized with calling ;
1961
; PID and given a socket number.                                  ;
5976 hidnplayr 1962
;                                                                 ;
1963
;  IN:  /                                                         ;
1964
;                                                                 ;
1965
; OUT:  eax = socket ptr on success                               ;
1966
;       eax = 0 on error                                          ;
1967
;       edi = socket number on success                            ;
1968
;                                                                 ;
1969
;-----------------------------------------------------------------;
3545 hidnplayr 1970
align 4
6011 hidnplayr 1971
socket_alloc:
3545 hidnplayr 1972
 
1973
        push    ebx
1974
 
6413 hidnplayr 1975
        stdcall kernel_alloc, SOCKET_STRUCT_SIZE
5969 hidnplayr 1976
        or      eax, eax
1977
        jz      .nomem
3556 hidnplayr 1978
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_alloc: ptr=%x\n", eax
3545 hidnplayr 1979
 
1980
; zero-initialize allocated memory
1981
        push    eax
1982
        mov     edi, eax
6413 hidnplayr 1983
        mov     ecx, SOCKET_STRUCT_SIZE / 4
3545 hidnplayr 1984
        xor     eax, eax
3711 clevermous 1985
        rep stosd
3545 hidnplayr 1986
        pop     eax
1987
 
1988
; set send-and receive procedures to return -1
3658 hidnplayr 1989
        mov     [eax + SOCKET.snd_proc], .not_yet
1990
        mov     [eax + SOCKET.rcv_proc], .not_yet
3545 hidnplayr 1991
 
3647 hidnplayr 1992
        pusha
1993
        mov     ecx, socket_mutex
1994
        call    mutex_lock
1995
        popa
1996
 
3545 hidnplayr 1997
; find first free socket number and use it
1998
        mov     edi, [last_socket_num]
1999
  .next_socket_number:
2000
        inc     edi
2001
        jz      .next_socket_number     ; avoid socket nr 0
2002
        cmp     edi, -1
2003
        je      .next_socket_number     ; avoid socket nr -1
2004
        mov     ebx, net_sockets
2005
  .next_socket:
2006
        mov     ebx, [ebx + SOCKET.NextPtr]
2007
        test    ebx, ebx
2008
        jz      .last_socket
2009
 
2010
        cmp     [ebx + SOCKET.Number], edi
2011
        jne     .next_socket
2012
        jmp     .next_socket_number
2013
 
2014
  .last_socket:
2015
        mov     [last_socket_num], edi
2016
        mov     [eax + SOCKET.Number], edi
3556 hidnplayr 2017
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_alloc: number=%u\n", edi
3545 hidnplayr 2018
 
2019
; Fill in PID
9692 Doczom 2020
        mov     ebx, [current_slot]
2021
        mov     ebx, [ebx + APPDATA.tid]
3545 hidnplayr 2022
        mov     [eax + SOCKET.PID], ebx
2023
        mov     [eax + SOCKET.TID], ebx         ; currently TID = PID in kolibrios :(
2024
 
2025
; init mutex
2026
        pusha
2027
        lea     ecx, [eax + SOCKET.mutex]
2028
        call    mutex_init
2029
        popa
2030
 
2031
; add socket to the list by re-arranging some pointers
2032
        mov     ebx, [net_sockets + SOCKET.NextPtr]
2033
 
2034
        mov     [eax + SOCKET.PrevPtr], net_sockets
2035
        mov     [eax + SOCKET.NextPtr], ebx
2036
 
2037
        test    ebx, ebx
2038
        jz      @f
2039
 
2040
        pusha
2041
        lea     ecx, [ebx + SOCKET.mutex]
2042
        call    mutex_lock
2043
        popa
2044
 
2045
        mov     [ebx + SOCKET.PrevPtr], eax
2046
 
2047
        pusha
2048
        lea     ecx, [ebx + SOCKET.mutex]
2049
        call    mutex_unlock
2050
        popa
2051
       @@:
2052
 
2053
        mov     [net_sockets + SOCKET.NextPtr], eax
3647 hidnplayr 2054
 
2055
        pusha
2056
        mov     ecx, socket_mutex
2057
        call    mutex_unlock
2058
        popa
3545 hidnplayr 2059
        pop     ebx
2060
 
2061
        ret
2062
 
5969 hidnplayr 2063
  .nomem:
2064
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_alloc: Out of memory!\n"
2065
        pop     ebx
2066
        ret
2067
 
3658 hidnplayr 2068
  .not_yet:
3673 hidnplayr 2069
        mov     dword[esp+20], ENOTCONN
3658 hidnplayr 2070
        mov     dword[esp+32], -1
2071
        ret
3545 hidnplayr 2072
 
3658 hidnplayr 2073
 
5976 hidnplayr 2074
;-----------------------------------------------------------------;
2075
;                                                                 ;
6011 hidnplayr 2076
; socket_free: Free socket data memory and remove socket from     ;
2077
; the list. Caller should lock and unlock socket_mutex.           ;
5976 hidnplayr 2078
;                                                                 ;
2079
;  IN:  eax = socket ptr                                          ;
2080
;                                                                 ;
2081
; OUT:  /                                                         ;
2082
;                                                                 ;
2083
;-----------------------------------------------------------------;
3545 hidnplayr 2084
align 4
6011 hidnplayr 2085
socket_free:
3545 hidnplayr 2086
 
3556 hidnplayr 2087
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: %x\n", eax
3545 hidnplayr 2088
 
6011 hidnplayr 2089
        call    socket_check
3545 hidnplayr 2090
        jz      .error
2091
 
2092
        push    ebx
2093
 
2094
        pusha
2095
        lea     ecx, [eax + SOCKET.mutex]
2096
        call    mutex_lock
2097
        popa
2098
 
5969 hidnplayr 2099
        cmp     [eax + SOCKET.Type], SOCK_STREAM
2100
        jne     .no_stream
3545 hidnplayr 2101
 
2102
        mov     ebx, eax
5969 hidnplayr 2103
        cmp     [eax + STREAM_SOCKET.rcv.start_ptr], 0
2104
        je      @f
2105
        stdcall free_kernel_space, [eax + STREAM_SOCKET.rcv.start_ptr]
2106
  @@:
2107
        cmp     [ebx + STREAM_SOCKET.snd.start_ptr], 0
2108
        je      @f
2109
        stdcall free_kernel_space, [ebx + STREAM_SOCKET.snd.start_ptr]
2110
  @@:
3545 hidnplayr 2111
        mov     eax, ebx
5969 hidnplayr 2112
  .no_stream:
3545 hidnplayr 2113
 
3652 hidnplayr 2114
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: freeing socket %x\n", eax
3545 hidnplayr 2115
        push    eax                             ; this will be passed to kernel_free
2116
        mov     ebx, [eax + SOCKET.NextPtr]
2117
        mov     eax, [eax + SOCKET.PrevPtr]
2118
 
3556 hidnplayr 2119
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: linking socket %x to socket %x\n", eax, ebx
3545 hidnplayr 2120
 
2121
        test    eax, eax
2122
        jz      @f
2123
        mov     [eax + SOCKET.NextPtr], ebx
2124
       @@:
2125
 
2126
        test    ebx, ebx
2127
        jz      @f
2128
        mov     [ebx + SOCKET.PrevPtr], eax
2129
       @@:
2130
 
2131
        call    kernel_free
2132
        pop     ebx
2133
 
3652 hidnplayr 2134
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_free: success!\n"
2135
 
2136
  .error:
3545 hidnplayr 2137
        ret
2138
 
5969 hidnplayr 2139
  .error1:
2140
        pop     ebx
5976 hidnplayr 2141
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_free: error!\n"
5969 hidnplayr 2142
        DEBUGF  DEBUG_NETWORK_ERROR, "socket ptr=0x%x caller=0x%x\n", eax, [esp]
2143
        ret
2144
 
5976 hidnplayr 2145
;-----------------------------------------------------------------;
2146
;                                                                 ;
6011 hidnplayr 2147
; socket_fork: Create a child socket.                             ;
5976 hidnplayr 2148
;                                                                 ;
2149
;  IN:  ebx = socket number                                       ;
2150
;                                                                 ;
2151
; OUT:  eax = child socket number on success                      ;
2152
;       eax = 0 on error                                          ;
2153
;                                                                 ;
2154
;-----------------------------------------------------------------;
3545 hidnplayr 2155
align 4
6011 hidnplayr 2156
socket_fork:
3545 hidnplayr 2157
 
3556 hidnplayr 2158
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_fork: %x\n", ebx
3545 hidnplayr 2159
 
2160
; Exit if backlog queue is full
2161
        mov     eax, [ebx + SOCKET_QUEUE_LOCATION + queue.size]
2162
        cmp     ax, [ebx + SOCKET.backlog]
2163
        jae     .fail
2164
 
2165
; Allocate new socket
2166
        push    ebx
6011 hidnplayr 2167
        call    socket_alloc
3545 hidnplayr 2168
        pop     ebx
4535 hidnplayr 2169
        test    eax, eax
3545 hidnplayr 2170
        jz      .fail
2171
 
2172
        push    eax
2173
        mov     esi, esp
2174
        add_to_queue (ebx + SOCKET_QUEUE_LOCATION), MAX_backlog, 4, .fail2
2175
        pop     eax
2176
 
2177
; Copy structure from current socket to new
3817 hidnplayr 2178
; We start at PID to preserve the socket num, 2 pointers and mutex
2179
; TID will be filled in later
3545 hidnplayr 2180
        lea     esi, [ebx + SOCKET.PID]
2181
        lea     edi, [eax + SOCKET.PID]
2182
        mov     ecx, (SOCKET_QUEUE_LOCATION - SOCKET.PID + 3)/4
3711 clevermous 2183
        rep movsd
3545 hidnplayr 2184
 
2185
        and     [eax + SOCKET.options], not SO_ACCEPTCON
2186
 
3817 hidnplayr 2187
; Notify owner of parent socket
2188
        push    eax
2189
        mov     eax, ebx
6011 hidnplayr 2190
        call    socket_notify
3817 hidnplayr 2191
        pop     eax
2192
 
3545 hidnplayr 2193
        ret
2194
 
2195
  .fail2:
2196
        add     esp, 4+4+4
2197
  .fail:
3556 hidnplayr 2198
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_fork: failed\n"
3545 hidnplayr 2199
        xor     eax, eax
2200
        ret
2201
 
2202
 
5976 hidnplayr 2203
;-----------------------------------------------------------------;
2204
;                                                                 ;
6011 hidnplayr 2205
; socket_num_to_ptr: Get socket structure address by its number.  ;
5976 hidnplayr 2206
;                                                                 ;
2207
;  IN:  ecx = socket number                                       ;
2208
;                                                                 ;
2209
; OUT:  eax = socket ptr                                          ;
2210
;       eax = 0 on error                                          ;
2211
;                                                                 ;
2212
;-----------------------------------------------------------------;
3545 hidnplayr 2213
align 4
6011 hidnplayr 2214
socket_num_to_ptr:
3545 hidnplayr 2215
 
3556 hidnplayr 2216
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_num_to_ptr: num=%u ", ecx
3545 hidnplayr 2217
 
3647 hidnplayr 2218
        pusha
2219
        mov     ecx, socket_mutex
2220
        call    mutex_lock
2221
        popa
2222
 
3545 hidnplayr 2223
        mov     eax, net_sockets
2224
  .next_socket:
2225
        mov     eax, [eax + SOCKET.NextPtr]
5969 hidnplayr 2226
        test    eax, eax
3545 hidnplayr 2227
        jz      .error
2228
        cmp     [eax + SOCKET.Number], ecx
2229
        jne     .next_socket
2230
 
3647 hidnplayr 2231
        pusha
2232
        mov     ecx, socket_mutex
2233
        call    mutex_unlock
2234
        popa
2235
 
3556 hidnplayr 2236
        DEBUGF  DEBUG_NETWORK_VERBOSE, "ptr=%x\n", eax
3545 hidnplayr 2237
        ret
2238
 
2239
  .error:
3647 hidnplayr 2240
        pusha
2241
        mov     ecx, socket_mutex
2242
        call    mutex_unlock
2243
        popa
2244
 
4574 hidnplayr 2245
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_num_to_ptr: socket %u not found!\n", eax
2246
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_num_to_ptr: caller = 0x%x\n", [esp]
3545 hidnplayr 2247
        ret
2248
 
2249
 
5976 hidnplayr 2250
;-----------------------------------------------------------------;
2251
;                                                                 ;
6011 hidnplayr 2252
; socket_ptr_to_num: Get socket number by its address.            ;
5976 hidnplayr 2253
;                                                                 ;
2254
;  IN:  eax = socket ptr                                          ;
2255
;                                                                 ;
2256
; OUT:  eax = socket number                                       ;
2257
;       eax = 0 on error                                          ;
2258
;       ZF = set on error                                         ;
2259
;                                                                 ;
2260
;-----------------------------------------------------------------;
3545 hidnplayr 2261
align 4
6011 hidnplayr 2262
socket_ptr_to_num:
3545 hidnplayr 2263
 
3556 hidnplayr 2264
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_ptr_to_num: ptr=%x ", eax
3545 hidnplayr 2265
 
6011 hidnplayr 2266
        call    socket_check
3545 hidnplayr 2267
        jz      .error
2268
 
2269
        mov     eax, [eax + SOCKET.Number]
2270
 
3556 hidnplayr 2271
        DEBUGF  DEBUG_NETWORK_VERBOSE, "num=%u\n", eax
3545 hidnplayr 2272
        ret
2273
 
2274
  .error:
3556 hidnplayr 2275
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_ptr_to_num: not found\n", eax
3545 hidnplayr 2276
        ret
2277
 
2278
 
5976 hidnplayr 2279
;-----------------------------------------------------------------;
2280
;                                                                 ;
6011 hidnplayr 2281
; socket_check: Checks if the given ptr is really a socket ptr.   ;
5976 hidnplayr 2282
;                                                                 ;
2283
;  IN:  eax = socket ptr                                          ;
2284
;                                                                 ;
2285
; OUT:  eax = 0 on error                                          ;
2286
;       ZF = set on error                                         ;
2287
;                                                                 ;
2288
;-----------------------------------------------------------------;
3545 hidnplayr 2289
align 4
6011 hidnplayr 2290
socket_check:
3545 hidnplayr 2291
 
3556 hidnplayr 2292
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_check: %x\n", eax
3545 hidnplayr 2293
 
5969 hidnplayr 2294
        test    eax, eax
2295
        jz      .error
3545 hidnplayr 2296
        push    ebx
2297
        mov     ebx, net_sockets
2298
 
2299
  .next_socket:
2300
        mov     ebx, [ebx + SOCKET.NextPtr]
2301
        or      ebx, ebx
2302
        jz      .done
2303
        cmp     ebx, eax
2304
        jnz     .next_socket
2305
 
2306
  .done:
2307
        mov     eax, ebx
2308
        test    eax, eax
2309
        pop     ebx
5969 hidnplayr 2310
        ret
3545 hidnplayr 2311
 
5969 hidnplayr 2312
  .error:
5976 hidnplayr 2313
        DEBUGF  DEBUG_NETWORK_ERROR, "SOCKET_check: called with argument 0\n"
5969 hidnplayr 2314
        DEBUGF  DEBUG_NETWORK_ERROR, "stack: 0x%x, 0x%x, 0x%x\n", [esp], [esp+4], [esp+8]
3545 hidnplayr 2315
        ret
2316
 
2317
 
2318
 
5976 hidnplayr 2319
;-----------------------------------------------------------------;
2320
;                                                                 ;
6011 hidnplayr 2321
; socket_check_owner: Check if the caller app owns the socket.    ;
5976 hidnplayr 2322
;                                                                 ;
2323
;  IN:  eax = socket ptr                                          ;
2324
;                                                                 ;
2325
; OUT:  ZF = true/false                                           ;
2326
;                                                                 ;
2327
;-----------------------------------------------------------------;
3545 hidnplayr 2328
align 4
6011 hidnplayr 2329
socket_check_owner:
3545 hidnplayr 2330
 
3556 hidnplayr 2331
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_check_owner: %x\n", eax
3545 hidnplayr 2332
 
2333
        push    ebx
9692 Doczom 2334
        mov     ebx, [current_slot]
2335
        mov     ebx, [ebx + APPDATA.tid]
3545 hidnplayr 2336
        cmp     [eax + SOCKET.PID], ebx
3711 clevermous 2337
        pop     ebx
3545 hidnplayr 2338
 
2339
        ret
2340
 
2341
 
2342
 
2343
 
5976 hidnplayr 2344
;-----------------------------------------------------------------;
2345
;                                                                 ;
6011 hidnplayr 2346
; socket_process_end: Kernel calls this function when a certain   ;
2347
; process ends. This function will check if the process had any   ;
2348
; open sockets and update them accordingly (clean up).            ;
5976 hidnplayr 2349
;                                                                 ;
2350
;  IN:  edx = pid                                                 ;
2351
;                                                                 ;
2352
; OUT:  /                                                         ;
2353
;                                                                 ;
2354
;-----------------------------------------------------------------;
3545 hidnplayr 2355
align 4
6011 hidnplayr 2356
socket_process_end:
3545 hidnplayr 2357
 
4436 hidnplayr 2358
        ret     ; FIXME
2359
 
4056 hidnplayr 2360
        cmp     [net_sockets + SOCKET.NextPtr], 0       ; Are there any active sockets at all?
2361
        je      .quickret                               ; nope, exit immediately
2362
 
2363
; TODO: run the following code in another thread, to avoid deadlock
2364
 
3556 hidnplayr 2365
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_process_end: %x\n", edx
3545 hidnplayr 2366
 
3647 hidnplayr 2367
        pusha
2368
        mov     ecx, socket_mutex
2369
        call    mutex_lock
2370
        popa
2371
 
3545 hidnplayr 2372
        push    ebx
2373
        mov     ebx, net_sockets
2374
 
2375
  .next_socket:
2376
        mov     ebx, [ebx + SOCKET.NextPtr]
2377
  .next_socket_test:
2378
        test    ebx, ebx
2379
        jz      .done
2380
 
2381
        cmp     [ebx + SOCKET.PID], edx
2382
        jne     .next_socket
2383
 
3556 hidnplayr 2384
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_process_end: killing socket %x\n", ebx
3545 hidnplayr 2385
 
2386
        mov     [ebx + SOCKET.PID], 0
2387
        mov     eax, ebx
2388
        mov     ebx, [ebx + SOCKET.NextPtr]
3648 hidnplayr 2389
 
3545 hidnplayr 2390
        pusha
3652 hidnplayr 2391
        cmp     [eax + SOCKET.Domain], AF_INET4
2392
        jne     .free
2393
 
2394
        cmp     [eax + SOCKET.Protocol], IP_PROTO_TCP
2395
        jne     .free
2396
 
6011 hidnplayr 2397
        call    tcp_disconnect
3652 hidnplayr 2398
        jmp     .closed
2399
 
2400
  .free:
6011 hidnplayr 2401
        call    socket_free
3652 hidnplayr 2402
 
2403
  .closed:
3545 hidnplayr 2404
        popa
2405
        jmp     .next_socket_test
2406
 
2407
  .done:
2408
        pop     ebx
2409
 
3647 hidnplayr 2410
        pusha
2411
        mov     ecx, socket_mutex
2412
        call    mutex_unlock
2413
        popa
2414
 
4056 hidnplayr 2415
  .quickret:
3545 hidnplayr 2416
        ret
2417
 
2418
 
2419
 
2420
 
5976 hidnplayr 2421
;-----------------------------------------------------------------;
2422
;                                                                 ;
6011 hidnplayr 2423
; socket_is_connecting: Update socket state.                      ;
5976 hidnplayr 2424
;                                                                 ;
2425
;  IN:  eax = socket ptr                                          ;
2426
;                                                                 ;
2427
;  OUT: /                                                         ;
2428
;                                                                 ;
2429
;-----------------------------------------------------------------;
3545 hidnplayr 2430
align 4
6011 hidnplayr 2431
socket_is_connecting:
3545 hidnplayr 2432
 
3556 hidnplayr 2433
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_connecting: %x\n", eax
3545 hidnplayr 2434
 
4025 hidnplayr 2435
        and     [eax + SOCKET.state], not (SS_ISCONNECTED + SS_ISDISCONNECTING + SS_ISCONFIRMING)
2436
        or      [eax + SOCKET.state], SS_ISCONNECTING
2437
        ret
3545 hidnplayr 2438
 
2439
 
2440
 
5976 hidnplayr 2441
;-----------------------------------------------------------------;
2442
;                                                                 ;
6011 hidnplayr 2443
; socket_is_connected: Update socket state.                       ;
5976 hidnplayr 2444
;                                                                 ;
2445
;  IN:  eax = socket ptr                                          ;
2446
;                                                                 ;
2447
;  OUT: /                                                         ;
2448
;                                                                 ;
2449
;-----------------------------------------------------------------;
3545 hidnplayr 2450
align 4
6011 hidnplayr 2451
socket_is_connected:
3545 hidnplayr 2452
 
3556 hidnplayr 2453
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_connected: %x\n", eax
3545 hidnplayr 2454
 
3674 hidnplayr 2455
        and     [eax + SOCKET.state], not (SS_ISCONNECTING + SS_ISDISCONNECTING + SS_ISCONFIRMING)
2456
        or      [eax + SOCKET.state], SS_ISCONNECTED
6011 hidnplayr 2457
        jmp     socket_notify
3545 hidnplayr 2458
 
2459
 
2460
 
2461
 
5976 hidnplayr 2462
;-----------------------------------------------------------------;
2463
;                                                                 ;
6011 hidnplayr 2464
; socket_is_disconnecting: Update socket state.                   ;
5976 hidnplayr 2465
;                                                                 ;
2466
;  IN:  eax = socket ptr                                          ;
2467
;                                                                 ;
2468
;  OUT: /                                                         ;
2469
;                                                                 ;
2470
;-----------------------------------------------------------------;
3545 hidnplayr 2471
align 4
6011 hidnplayr 2472
socket_is_disconnecting:
3545 hidnplayr 2473
 
3556 hidnplayr 2474
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_disconnecting: %x\n", eax
3545 hidnplayr 2475
 
3674 hidnplayr 2476
        and     [eax + SOCKET.state], not (SS_ISCONNECTING)
2477
        or      [eax + SOCKET.state], SS_ISDISCONNECTING + SS_CANTRCVMORE + SS_CANTSENDMORE
6011 hidnplayr 2478
        jmp     socket_notify
3545 hidnplayr 2479
 
2480
 
2481
 
5976 hidnplayr 2482
;-----------------------------------------------------------------;
2483
;                                                                 ;
6011 hidnplayr 2484
; socket_is_disconnected: Update socket state.                    ;
5976 hidnplayr 2485
;                                                                 ;
2486
;  IN:  eax = socket ptr                                          ;
2487
;                                                                 ;
2488
;  OUT: /                                                         ;
2489
;                                                                 ;
2490
;-----------------------------------------------------------------;
3545 hidnplayr 2491
align 4
6011 hidnplayr 2492
socket_is_disconnected:
3545 hidnplayr 2493
 
8027 hidnplayr 2494
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_is_disconnected: %x\n", eax
3545 hidnplayr 2495
 
3674 hidnplayr 2496
        and     [eax + SOCKET.state], not (SS_ISCONNECTING + SS_ISCONNECTED + SS_ISDISCONNECTING)
2497
        or      [eax + SOCKET.state], SS_CANTRCVMORE + SS_CANTSENDMORE
6011 hidnplayr 2498
        jmp     socket_notify
3545 hidnplayr 2499
 
2500
 
2501
 
5976 hidnplayr 2502
;-----------------------------------------------------------------;
2503
;                                                                 ;
6011 hidnplayr 2504
; socket_cant_recv_more: Update socket state.                     ;
5976 hidnplayr 2505
;                                                                 ;
2506
;  IN:  eax = socket ptr                                          ;
2507
;                                                                 ;
2508
;  OUT: /                                                         ;
2509
;                                                                 ;
2510
;-----------------------------------------------------------------;
3545 hidnplayr 2511
align 4
6011 hidnplayr 2512
socket_cant_recv_more:
3545 hidnplayr 2513
 
3556 hidnplayr 2514
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_cant_recv_more: %x\n", eax
3545 hidnplayr 2515
 
3674 hidnplayr 2516
        or      [eax + SOCKET.state], SS_CANTRCVMORE
6011 hidnplayr 2517
        jmp     socket_notify
3545 hidnplayr 2518
 
3565 hidnplayr 2519
 
3545 hidnplayr 2520
 
5976 hidnplayr 2521
;-----------------------------------------------------------------;
2522
;                                                                 ;
6011 hidnplayr 2523
; socket_cant_send_more: Update socket state.                     ;
5976 hidnplayr 2524
;                                                                 ;
2525
;  IN:  eax = socket ptr                                          ;
2526
;                                                                 ;
2527
;  OUT: /                                                         ;
2528
;                                                                 ;
2529
;-----------------------------------------------------------------;
3545 hidnplayr 2530
align 4
6011 hidnplayr 2531
socket_cant_send_more:
3545 hidnplayr 2532
 
3556 hidnplayr 2533
        DEBUGF  DEBUG_NETWORK_VERBOSE, "SOCKET_cant_send_more: %x\n", eax
3545 hidnplayr 2534
 
3674 hidnplayr 2535
        or      [eax + SOCKET.state], SS_CANTSENDMORE
3658 hidnplayr 2536
        mov     [eax + SOCKET.snd_proc], .notconn
6011 hidnplayr 2537
        jmp     socket_notify
3545 hidnplayr 2538
 
3658 hidnplayr 2539
  .notconn:
9917 Doczom 2540
        mov     dword[esp + SYSCALL_STACK.ebx], ENOTCONN
2541
        mov     dword[esp + SYSCALL_STACK.eax], -1
5356 serge 2542
        ret