Subversion Repositories Kolibri OS

Rev

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

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