Subversion Repositories Kolibri OS

Rev

Rev 5596 | Rev 6078 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 5596 Rev 5984
Line 14... Line 14...
14
;;          GNU GENERAL PUBLIC LICENSE                             ;;
14
;;          GNU GENERAL PUBLIC LICENSE                             ;;
15
;;             Version 2, June 1991                                ;;
15
;;             Version 2, June 1991                                ;;
16
;;                                                                 ;;
16
;;                                                                 ;;
17
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
17
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Line 18... Line 18...
18
 
18
 
Line 19... Line 19...
19
$Revision: 5584 $
19
$Revision: 5842 $
20
 
20
 
Line 21... Line 21...
21
IPv4_MAX_FRAGMENTS              = 64
21
IPv4_MAX_FRAGMENTS              = 64
Line 213... Line 213...
213
;  and call appropriate handler. (TCP/UDP/ICMP/..)
213
;  and call appropriate handler. (TCP/UDP/ICMP/..)
214
;
214
;
215
;  It will also re-construct fragmented packets
215
;  It will also re-construct fragmented packets
216
;
216
;
217
;  IN:  Pointer to buffer in [esp]
217
;  IN:  Pointer to buffer in [esp]
218
;       size of buffer in [esp+4]
-
 
219
;       pointer to device struct in ebx
218
;       pointer to device struct in ebx
220
;       pointer to IPv4 header in edx
219
;       pointer to IPv4 header in edx
221
;       size of IPv4 packet in ecx
220
;       size of IPv4 packet in ecx
222
;  OUT: /
221
;  OUT: /
223
;
222
;
224
;-----------------------------------------------------------------
223
;-----------------------------------------------------------------
225
align 4
224
align 4
226
IPv4_input:                                                     ; TODO: add IPv4 raw sockets support
225
IPv4_input:
Line 227... Line 226...
227
 
226
 
228
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: packet from %u.%u.%u.%u ",\
227
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: packet from %u.%u.%u.%u ",\
229
        [edx + IPv4_header.SourceAddress + 0]:1,[edx + IPv4_header.SourceAddress + 1]:1,\
228
        [edx + IPv4_header.SourceAddress + 0]:1,[edx + IPv4_header.SourceAddress + 1]:1,\
230
        [edx + IPv4_header.SourceAddress + 2]:1,[edx + IPv4_header.SourceAddress + 3]:1
229
        [edx + IPv4_header.SourceAddress + 2]:1,[edx + IPv4_header.SourceAddress + 3]:1
231
        DEBUGF  DEBUG_NETWORK_VERBOSE, "to %u.%u.%u.%u\n",\
230
        DEBUGF  DEBUG_NETWORK_VERBOSE, "to %u.%u.%u.%u\n",\
232
        [edx + IPv4_header.DestinationAddress + 0]:1,[edx + IPv4_header.DestinationAddress + 1]:1,\
231
        [edx + IPv4_header.DestinationAddress + 0]:1,[edx + IPv4_header.DestinationAddress + 1]:1,\
Line -... Line 232...
-
 
232
        [edx + IPv4_header.DestinationAddress + 2]:1,[edx + IPv4_header.DestinationAddress + 3]:1
-
 
233
 
-
 
234
        call    NET_ptr_to_num4
-
 
235
        cmp     edi, -1
233
        [edx + IPv4_header.DestinationAddress + 2]:1,[edx + IPv4_header.DestinationAddress + 3]:1
236
        je      .invalid_device
234
 
237
 
Line 235... Line 238...
235
;-------------------------------
238
;-------------------------------
236
; re-calculate the checksum
239
; re-calculate the checksum
Line 237... Line 240...
237
 
240
 
Line 238... Line 241...
238
        IPv4_checksum edx
241
        IPv4_checksum edx
239
        jnz     .dump                                           ; if checksum isn't valid then dump packet
242
        jnz     .dump                                           ; if checksum isn't valid then dump packet
240
 
-
 
241
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Checksum ok\n"
-
 
242
 
-
 
243
;-----------------------------------
-
 
Line -... Line 243...
-
 
243
 
244
; Check if destination IP is correct
244
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: Checksum ok\n"
245
 
245
 
246
        call    NET_ptr_to_num4
246
;--------------------------------
Line 247... Line 247...
247
 
247
; Check if destination IP matches
248
        ; check if it matches local ip (Using RFC1122 strong end system model)
-
 
249
 
248
 
250
        mov     eax, [edx + IPv4_header.DestinationAddress]
249
; local ip (Using RFC1122 strong end system model)
Line 251... Line 250...
251
        cmp     eax, [IP_LIST + edi]
250
        mov     eax, [edx + IPv4_header.DestinationAddress]
252
        je      .ip_ok
-
 
253
 
251
        cmp     eax, [IP_LIST + edi]
254
        ; check for broadcast (IP or (not SUBNET))
252
        je      .ip_ok
Line 255... Line 253...
255
 
253
 
256
        cmp     eax, [BROADCAST_LIST + edi]
-
 
257
        je      .ip_ok
254
; network layer broadcast
258
 
255
        cmp     eax, [BROADCAST_LIST + edi]
259
        ; or a special broadcast (255.255.255.255)
256
        je      .ip_ok
Line 260... Line 257...
260
 
257
 
261
        cmp     eax, 0xffffffff
-
 
262
        je      .ip_ok
258
; physical layer broadcast (255.255.255.255)
263
 
259
        cmp     eax, 0xffffffff
Line 264... Line 260...
264
        ; maybe it's a multicast (224.0.0.0/4)
260
        je      .ip_ok
265
 
-
 
266
        and     eax, 0x0fffffff
261
 
267
        cmp     eax, 224
262
; multicast (224.0.0.0/4 = 224.0.0.0 to 239.255.255.255)
Line 268... Line 263...
268
        je      .ip_ok
263
        and     eax, 0x0fffffff
269
 
264
        cmp     eax, 224
Line 303... Line 298...
303
 
298
 
304
        movzx   ecx, [edx + IPv4_header.TotalLength]            ; Calculate length of encapsulated Packet
299
        movzx   ecx, [edx + IPv4_header.TotalLength]            ; Calculate length of encapsulated Packet
305
        xchg    cl, ch                                          ;
300
        xchg    cl, ch                                          ;
Line 306... Line -...
306
        sub     ecx, esi                                        ;
-
 
307
 
301
        sub     ecx, esi                                        ;
308
        lea     edi, [edx + IPv4_header.SourceAddress]          ; make edi ptr to source and dest IPv4 address
302
 
Line 309... Line 303...
309
        mov     al, [edx + IPv4_header.Protocol]
303
        mov     al, [edx + IPv4_header.Protocol]
310
        add     esi, edx                                        ; make esi ptr to data
304
        add     esi, edx                                        ; make esi ptr to data
Line 316... Line 310...
316
        je      UDP_input
310
        je      UDP_input
Line 317... Line 311...
317
 
311
 
318
        cmp     al, IP_PROTO_ICMP
312
        cmp     al, IP_PROTO_ICMP
Line -... Line 313...
-
 
313
        je      ICMP_input
-
 
314
 
-
 
315
;-------------------------------
-
 
316
; Look for a matching RAW socket
-
 
317
        pusha
-
 
318
        mov     ecx, socket_mutex
-
 
319
        call    mutex_lock
-
 
320
        popa
-
 
321
 
-
 
322
        add     ecx, esi
-
 
323
        sub     ecx, edx
-
 
324
        mov     esi, edx
-
 
325
        movzx   edx, al
-
 
326
        mov     eax, net_sockets
-
 
327
  .next_socket:
-
 
328
        mov     eax, [eax + SOCKET.NextPtr]
-
 
329
        or      eax, eax
-
 
330
        jz      .dump_unlock
-
 
331
 
-
 
332
        cmp     [eax + SOCKET.Domain], AF_INET4
-
 
333
        jne     .next_socket
-
 
334
 
-
 
335
        cmp     [eax + SOCKET.Protocol], edx
-
 
336
        jne     .next_socket
-
 
337
 
-
 
338
        pusha
-
 
339
        mov     ecx, socket_mutex
-
 
340
        call    mutex_unlock
-
 
341
        popa
-
 
342
 
-
 
343
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: found matching RAW socket: 0x%x\n", eax
-
 
344
 
-
 
345
        pusha
-
 
346
        lea     ecx, [eax + SOCKET.mutex]
-
 
347
        call    mutex_lock
-
 
348
        popa
-
 
349
 
-
 
350
        jmp     SOCKET_input
-
 
351
 
-
 
352
  .dump_unlock:
-
 
353
 
-
 
354
        pusha
-
 
355
        mov     ecx, socket_mutex
-
 
356
        call    mutex_unlock
319
        je      ICMP_input
357
        popa
Line 320... Line 358...
320
 
358
 
321
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: unknown protocol %u\n", al
359
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: unknown protocol %u\n", al
322
 
360
 
-
 
361
  .dump:
-
 
362
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: dumping\n"
-
 
363
        inc     [IPv4_packets_dumped + edi]
-
 
364
        call    NET_BUFF_free
-
 
365
        ret
323
  .dump:
366
 
324
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_input: dumping\n"
367
  .invalid_device:
Line 325... Line 368...
325
        inc     [IPv4_packets_dumped]                           ; FIXME: use correct interface
368
        DEBUGF  DEBUG_NETWORK_ERROR, "IPv4_input: packet originated from invalid device\n"
Line 566... Line 609...
566
 
609
 
567
;------------------------------------------------------------------
610
;------------------------------------------------------------------
568
;
611
;
569
; IPv4_output
612
; IPv4_output
570
;
613
;
-
 
614
; IN:    al = protocol
571
; IN:   eax = Destination IP
615
;        ah = TTL
572
;       ebx = device ptr (or 0 to let IP layer decide)
616
;       ebx = device ptr (or 0 to let IP layer decide)
573
;       ecx = data length
617
;       ecx = data length
574
;       edx = Source IP
618
;       edx = Source IP
575
;        di = TTL shl 8 + protocol
619
;       edi = Destination IP
576
;
620
;
577
; OUT:  eax = pointer to buffer start / 0 on error
621
; OUT:  eax = pointer to buffer start / 0 on error
578
;       ebx = device ptr (send packet through this device)
622
;       ebx = device ptr (send packet through this device)
579
;       ecx = data length
623
;       ecx = data length
Line 587... Line 631...
587
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_output: size=%u ip=0x%x\n", ecx, eax
631
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_output: size=%u ip=0x%x\n", ecx, eax
Line 588... Line 632...
588
 
632
 
589
        cmp     ecx, 65500              ; Max IPv4 packet size
633
        cmp     ecx, 65500              ; Max IPv4 packet size
Line 590... Line 634...
590
        ja      .too_large
634
        ja      .too_large
-
 
635
 
591
 
636
        push    ecx ax edi
592
        push    ecx di eax
637
        mov     eax, edi
593
        call    IPv4_route              ; outputs device number in edi, dest ip in eax, source IP in edx
638
        call    IPv4_route              ; outputs device number in edi, dest ip in eax, source IP in edx
594
        push    edx
639
        push    edx
Line 599... Line 644...
599
        test    eax, 0xffff0000         ; error bits
644
        test    eax, 0xffff0000         ; error bits
600
        jnz     .arp_error
645
        jnz     .arp_error
601
        push    ebx                     ; push the mac onto the stack
646
        push    ebx                     ; push the mac onto the stack
602
        push    ax
647
        push    ax
Line 603... Line 648...
603
 
648
 
Line 604... Line 649...
604
        inc     [IPv4_packets_tx + edi]   ; update stats
649
        inc     [IPv4_packets_tx + edi] ; update stats
605
 
650
 
606
        mov     ax, ETHER_PROTO_IPv4
651
        mov     ax, ETHER_PROTO_IPv4
607
        mov     ebx, [NET_DRV_LIST + edi]
652
        mov     ebx, [NET_DRV_LIST + edi]
Line 640... Line 685...
640
        xor     eax, eax
685
        xor     eax, eax
641
        ret
686
        ret
Line 642... Line 687...
642
 
687
 
643
  .arp_error:
688
  .arp_error:
-
 
689
        DEBUGF  DEBUG_NETWORK_ERROR, "IPv4_output: ARP error=%x\n", eax
-
 
690
        add     esp, 4
-
 
691
        pop     eax
644
        DEBUGF  DEBUG_NETWORK_ERROR, "IPv4_output: ARP error=%x\n", eax
692
        DEBUGF  DEBUG_NETWORK_ERROR, "IPv4_output: ip=0x%x\n", eax
645
        add     esp, 3*4+2
693
        add     esp, 4+2
646
        xor     eax, eax
694
        xor     eax, eax
Line 647... Line 695...
647
        ret
695
        ret
648
 
696
 
Line 676... Line 724...
676
align 4
724
align 4
677
IPv4_output_raw:
725
IPv4_output_raw:
Line 678... Line 726...
678
 
726
 
Line 679... Line -...
679
        DEBUGF 1,"IPv4_output_raw: size=%u ptr=%x socket=%x\n", ecx, esi, eax
-
 
680
 
-
 
681
        cmp     ecx, 1480               ;;;;; FIXME
-
 
682
        ja      .too_large
727
        DEBUGF 1,"IPv4_output_raw: size=%u ptr=%x socket=%x\n", ecx, esi, eax
683
 
728
 
Line 684... Line 729...
684
        sub     esp, 8
729
        sub     esp, 8
685
        push    esi eax
730
        push    esi eax
Line 705... Line 750...
705
 
750
 
706
        mov     dword[esp+4+4], edx
751
        mov     dword[esp+4+4], edx
Line 707... Line 752...
707
        mov     dword[esp+4+4+4], eax
752
        mov     dword[esp+4+4+4], eax
708
 
753
 
Line 709... Line 754...
709
        pop     eax esi
754
        pop     eax esi
710
;; todo: check socket options if we should add header, or just compute checksum
755
;; TODO: check socket options if we should add header, or just compute checksum
711
 
756
 
Line 732... Line 777...
732
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_output_raw: device=%x\n", ebx
777
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_output_raw: device=%x\n", ebx
733
        call    [ebx + NET_DEVICE.transmit]
778
        call    [ebx + NET_DEVICE.transmit]
734
        ret
779
        ret
Line 735... Line 780...
735
 
780
 
736
  .error:
781
  .error:
-
 
782
        add     esp, 6+8+4+4
-
 
783
        mov     ebx, ENOBUFS            ; FIXME: NOBUFS or MSGSIZE error
-
 
784
        or      eax, -1
-
 
785
        ret
737
        add     esp, 6
786
 
738
  .arp_error:
787
  .arp_error:
739
        add     esp, 8+4+4
-
 
740
  .too_large:
788
        add     esp, 8+4+4
741
        DEBUGF  DEBUG_NETWORK_ERROR, "IPv4_output_raw: Failed\n"
789
        mov     ebx, ENOTCONN
742
        or      eax, -1
790
        or      eax, -1
Line 743... Line 791...
743
        ret
791
        ret
744
 
792
 
745
 
793
 
746
;--------------------------------------------------------
794
;--------------------------------------------------------
747
;
795
;
748
;
796
;
749
; IN: dword [esp] = pointer to buffer containing ipv4 packet to be fragmented
797
; IN: [esp] = pointer to buffer containing ipv4 packet to be fragmented
750
;     esi = pointer to ip header in that buffer
798
;     edi = pointer to ip header in that buffer
751
;     ecx = max size of fragments
799
;     ebx = device ptr
752
;
800
;
-
 
801
; OUT: /
Line 753... Line 802...
753
; OUT: /
802
;
-
 
803
;--------------------------------------------------------
-
 
804
proc IPv4_fragment stdcall buffer
-
 
805
 
-
 
806
locals
-
 
807
        offset          dd ?
754
;
808
        headerlength    dd ?
-
 
809
        headerptr       dd ?
Line 755... Line 810...
755
;--------------------------------------------------------
810
        dataptr         dd ?
Line 756... Line 811...
756
 
811
        remaining       dd ?
757
align 4
-
 
758
IPv4_fragment:
812
        segmentsize     dd ?
759
 
813
endl
760
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_fragment\n"
-
 
761
 
814
 
762
        and     ecx, not 111b   ; align 4
-
 
763
 
815
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_fragment\n"
764
        cmp     ecx, sizeof.IPv4_header + 8     ; must be able to put at least 8 bytes
816
 
765
        jb      .err2
817
; We must be able to put at least 8 bytes per segment
766
 
818
        movzx   eax, byte[edi]          ; IHL
767
        push    esi ecx
-
 
768
        mov     eax, [esi + IPv4_header.DestinationAddress]
819
        and     eax, 0xf
769
        call    ARP_IP_to_MAC
820
        shl     eax, 2
Line 770... Line -...
770
        pop     ecx esi
-
 
771
        cmp     eax, -1
821
        mov     [headerlength], eax
772
        jz      .err2
-
 
Line -... Line 822...
-
 
822
        add     eax, 8
-
 
823
        mov     ecx, [ebx + NET_DEVICE.mtu]
-
 
824
        and     ecx, not 11b
-
 
825
        cmp     ecx, eax
-
 
826
        jb      .fail
-
 
827
 
-
 
828
        mov     [edi + IPv4_header.HeaderChecksum], 0
Line 773... Line -...
773
 
-
 
774
        push    ebx
829
 
775
        push    ax
-
 
776
 
830
        mov     [segmentsize], ecx
Line 777... Line 831...
777
        mov     ebx, [NET_DRV_LIST]
831
        mov     [headerptr], edi
778
        lea     eax, [ebx + ETH_DEVICE.mac]
832
        movzx   ecx, [edi + IPv4_header.TotalLength]
Line -... Line 833...
-
 
833
        xchg    cl, ch
-
 
834
        sub     ecx, [headerlength]
-
 
835
        mov     [remaining], ecx
-
 
836
        mov     [offset], 0
-
 
837
 
-
 
838
        add     edi, [headerlength]
779
        push    eax
839
        mov     [dataptr], edi
780
 
840
 
-
 
841
  .loop:
-
 
842
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Ipv4_fragment: new fragment"
781
 
843
 
782
        push    esi                             ; ptr to ip header
844
        mov     ecx, [segmentsize]
-
 
845
        cmp     ecx, [remaining]
-
 
846
        jbe     @f
-
 
847
        mov     ecx, [remaining]
Line 783... Line 848...
783
        sub     ecx, sizeof.IPv4_header         ; substract header size
848
  @@:
784
        push    ecx                             ; max data size
849
 
785
        push    dword 0                         ; offset
850
        mov     ax, ETHER_PROTO_IPv4
-
 
851
        mov     edx, [esp]
786
 
852
        add     edx, [edx + NET_BUFF.offset]
Line 787... Line 853...
787
  .new_fragment:
853
;        add     edx, ETH_header.DstMAC         ; = 0
788
        DEBUGF  DEBUG_NETWORK_VERBOSE, "Ipv4_fragment: new fragment"
854
        call    ETH_output
789
 
855
        jz      .fail
790
        mov     ax, ETHER_PROTO_IPv4
856
 
791
        lea     ebx, [esp + 4*4]
-
 
792
        call    ETH_output
857
        push    edi
793
        jz      .err
858
        mov     edx, ecx
794
 
859
 
-
 
860
; copy header
Line 795... Line 861...
795
; copy header
861
        mov     esi, [headerptr]
796
        mov     esi, [esp + 2*4]
862
        mov     ecx, [headerlength]
797
        mov     ecx, 5  ; 5 dwords: TODO: use IHL field of the header!
-
 
798
        rep movsd
863
        shr     ecx, 2
799
 
-
 
800
; copy data
-
 
801
        mov     esi, [esp + 2*4]
-
 
802
        add     esi, sizeof.IPv4_header
864
        rep movsd
803
        add     esi, [esp]      ; offset
-
 
804
 
-
 
805
        mov     ecx, [esp + 1*4]
-
 
806
        DEBUGF  DEBUG_NETWORK_VERBOSE, "IPv4_fragment: copying %u bytes\n", ecx
-
 
807
        rep movsb
-
 
808
 
865
 
Line -... Line 866...
-
 
866
; copy data
809
; now, correct header
867
        mov     esi, [dataptr]
-
 
868
        add     esi, [offset]
Line -... Line 869...
-
 
869
        mov     ecx, edx
-
 
870
        sub     ecx, [headerlength]
-
 
871
        shr     ecx, 2
-
 
872
        rep movsd
810
        mov     ecx, [esp + 1*4]
873
        pop     edi
811
        add     ecx, sizeof.IPv4_header
874
 
-
 
875
; now, correct header
-
 
876
; packet length
Line 812... Line 877...
812
        xchg    cl, ch
877
        mov     ax, dx
813
        mov     [edi + IPv4_header.TotalLength], cx
878
        xchg    al, ah
814
 
-
 
815
        mov     ecx, [esp]              ; offset
879
        mov     [edi + IPv4_header.TotalLength], ax
816
        xchg    cl, ch
-
 
Line 817... Line 880...
817
 
880
 
818
;        cmp     dword[esp + 4*4], 0     ; last fragment?;<<<<<<
881
; offset
Line 819... Line -...
819
;        je      .last_fragment
-
 
820
        or      cx, 1 shl 2             ; more fragments
-
 
821
;  .last_fragment:
-
 
822
        mov     [edi + IPv4_header.FlagsAndFragmentOffset], cx
-
 
823
 
-
 
824
        mov     [edi + IPv4_header.HeaderChecksum], 0
-
 
825
 
-
 
826
        ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<< send the packet
-
 
827
        mov     ecx, [esp + 1*4]
882
        mov     eax, [offset]
828
 
-
 
829
        push    edx eax
-
 
830
        IPv4_checksum edi
883
        xchg    al, ah
Line 831... Line 884...
831
 
884
 
832
        call    [ebx + NET_DEVICE.transmit]
885
        sub     edx, [headerlength]
833
        ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
-
 
834
 
-
 
835
        mov     ecx, [esp+4]
-
 
836
        add     [esp], ecx
-
 
837
 
886
        sub     [remaining], edx
838
        mov     ecx, [esp+3*4+6+4]      ; ptr to begin of buff
887
        je      @f
Line -... Line 888...
-
 
888
        jb      .fail
-
 
889
        or      ah, 1 shl 2             ; more fragments
Line 839... Line 890...
839
        add     ecx, [esp+3*4+6+4+4]    ; buff size
890
        add     [offset], edx
840
        sub     ecx, [esp+2*4]          ; ptr to ip header
891
  @@:
841
        add     ecx, [esp]              ; offset
892
        mov     [edi + IPv4_header.FlagsAndFragmentOffset], ax
Line 971... Line 1022...
971
 
1022
 
972
; Fill in remote IP
1023
; Fill in remote IP
973
        pushd   [edx + 4]
1024
        pushd   [edx + 4]
Line 974... Line -...
974
        pop     [eax + IP_SOCKET.RemoteIP]
-
 
975
 
-
 
976
; Set up data receiving queue
-
 
977
        push    eax
-
 
978
        init_queue (eax + SOCKET_QUEUE_LOCATION)
-
 
979
        pop     eax
1025
        pop     [eax + IP_SOCKET.RemoteIP]
980
 
1026
 
Line 981... Line 1027...
981
        lea     ecx, [eax + SOCKET.mutex]
1027
        lea     ecx, [eax + SOCKET.mutex]
982
        call    mutex_unlock
1028
        call    mutex_unlock