Subversion Repositories Kolibri OS

Rev

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

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