Mercurial > pidgin
comparison libpurple/network.c @ 25436:cddd7961901f
propagate from branch 'im.pidgin.pidgin' (head 32e078dbbf6d15a1c0a2916f1d590ea45f3c364d)
to branch 'im.pidgin.pidgin.openq' (head 2634a1410370cffba5172a684edbe1009b78107a)
author | SHiNE CsyFeK <csyfek@gmail.com> |
---|---|
date | Sun, 08 Feb 2009 10:34:31 +0000 |
parents | 75f72178e361 |
children | 4b8c4870b13a af42303654a5 |
comparison
equal
deleted
inserted
replaced
25232:effbf24b39b1 | 25436:cddd7961901f |
---|---|
69 static NMState nm_state = NM_STATE_UNKNOWN; | 69 static NMState nm_state = NM_STATE_UNKNOWN; |
70 static gboolean have_nm_state = FALSE; | 70 static gboolean have_nm_state = FALSE; |
71 | 71 |
72 #elif defined _WIN32 | 72 #elif defined _WIN32 |
73 static int current_network_count; | 73 static int current_network_count; |
74 | |
75 /* Mutex for the other global vars */ | |
76 static GStaticMutex mutex = G_STATIC_MUTEX_INIT; | |
77 static gboolean network_initialized = FALSE; | |
78 static HANDLE network_change_handle = NULL; | |
79 static int (WSAAPI *MyWSANSPIoctl) ( | |
80 HANDLE hLookup, DWORD dwControlCode, LPVOID lpvInBuffer, | |
81 DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer, | |
82 LPDWORD lpcbBytesReturned, LPWSACOMPLETION lpCompletion) = NULL; | |
74 #endif | 83 #endif |
75 | 84 |
76 struct _PurpleNetworkListenData { | 85 struct _PurpleNetworkListenData { |
77 int listenfd; | 86 int listenfd; |
78 int socket_type; | 87 int socket_type; |
531 current_network_count = new_count; | 540 current_network_count = new_count; |
532 | 541 |
533 return FALSE; | 542 return FALSE; |
534 } | 543 } |
535 | 544 |
545 static gboolean _print_debug_msg(gpointer data) { | |
546 gchar *msg = data; | |
547 purple_debug_warning("network", msg); | |
548 g_free(msg); | |
549 return FALSE; | |
550 } | |
551 | |
536 static gpointer wpurple_network_change_thread(gpointer data) | 552 static gpointer wpurple_network_change_thread(gpointer data) |
537 { | 553 { |
538 HANDLE h; | |
539 WSAQUERYSET qs; | 554 WSAQUERYSET qs; |
540 time_t last_trigger = time(NULL); | 555 WSAEVENT *nla_event; |
541 | 556 time_t last_trigger = time(NULL) - 31; |
542 int (WSAAPI *MyWSANSPIoctl) ( | 557 char buf[4096]; |
543 HANDLE hLookup, DWORD dwControlCode, LPVOID lpvInBuffer, | 558 WSAQUERYSET *res = (LPWSAQUERYSET) buf; |
544 DWORD cbInBuffer, LPVOID lpvOutBuffer, DWORD cbOutBuffer, | 559 DWORD size; |
545 LPDWORD lpcbBytesReturned, LPWSACOMPLETION lpCompletion) = NULL; | 560 |
546 | 561 if ((nla_event = WSACreateEvent()) == WSA_INVALID_EVENT) { |
547 if (!(MyWSANSPIoctl = (void*) wpurple_find_and_loadproc("ws2_32.dll", "WSANSPIoctl"))) { | 562 int errorid = WSAGetLastError(); |
563 gchar *msg = g_win32_error_message(errorid); | |
564 purple_timeout_add(0, _print_debug_msg, | |
565 g_strdup_printf("Couldn't create WSA event. " | |
566 "Message: %s (%d).\n", msg, errorid)); | |
567 g_free(msg); | |
548 g_thread_exit(NULL); | 568 g_thread_exit(NULL); |
549 return NULL; | 569 return NULL; |
550 } | 570 } |
551 | 571 |
552 while (TRUE) { | 572 while (TRUE) { |
553 int retval; | 573 int retval; |
554 DWORD retLen = 0; | 574 DWORD retLen = 0; |
555 | 575 WSACOMPLETION completion; |
556 memset(&qs, 0, sizeof(WSAQUERYSET)); | 576 WSAOVERLAPPED overlapped; |
557 qs.dwSize = sizeof(WSAQUERYSET); | 577 |
558 qs.dwNameSpace = NS_NLA; | 578 g_static_mutex_lock(&mutex); |
559 if (WSALookupServiceBegin(&qs, 0, &h) == SOCKET_ERROR) { | 579 if (network_initialized == FALSE) { |
560 int errorid = WSAGetLastError(); | 580 /* purple_network_uninit has been called */ |
561 gchar *msg = g_win32_error_message(errorid); | 581 WSACloseEvent(nla_event); |
562 purple_debug_warning("network", "Couldn't retrieve NLA SP lookup handle. " | 582 g_static_mutex_unlock(&mutex); |
563 "NLA service is probably not running. Message: %s (%d).\n", | |
564 msg, errorid); | |
565 g_free(msg); | |
566 g_thread_exit(NULL); | 583 g_thread_exit(NULL); |
567 return NULL; | 584 return NULL; |
585 } | |
586 | |
587 if (network_change_handle == NULL) { | |
588 memset(&qs, 0, sizeof(WSAQUERYSET)); | |
589 qs.dwSize = sizeof(WSAQUERYSET); | |
590 qs.dwNameSpace = NS_NLA; | |
591 if (WSALookupServiceBegin(&qs, 0, &network_change_handle) == SOCKET_ERROR) { | |
592 int errorid = WSAGetLastError(); | |
593 gchar *msg = g_win32_error_message(errorid); | |
594 purple_timeout_add(0, _print_debug_msg, | |
595 g_strdup_printf("Couldn't retrieve NLA SP lookup handle. " | |
596 "NLA service is probably not running. Message: %s (%d).\n", | |
597 msg, errorid)); | |
598 g_free(msg); | |
599 WSACloseEvent(nla_event); | |
600 g_static_mutex_unlock(&mutex); | |
601 g_thread_exit(NULL); | |
602 return NULL; | |
603 } | |
604 } | |
605 g_static_mutex_unlock(&mutex); | |
606 | |
607 memset(&completion, 0, sizeof(WSACOMPLETION)); | |
608 completion.Type = NSP_NOTIFY_EVENT; | |
609 overlapped.hEvent = nla_event; | |
610 completion.Parameters.Event.lpOverlapped = &overlapped; | |
611 | |
612 if (MyWSANSPIoctl(network_change_handle, SIO_NSP_NOTIFY_CHANGE, NULL, 0, NULL, 0, &retLen, &completion) == SOCKET_ERROR) { | |
613 int errorid = WSAGetLastError(); | |
614 if (errorid == WSA_INVALID_HANDLE) { | |
615 purple_timeout_add(0, _print_debug_msg, | |
616 g_strdup("Invalid NLA handle; resetting.\n")); | |
617 g_static_mutex_lock(&mutex); | |
618 retval = WSALookupServiceEnd(network_change_handle); | |
619 network_change_handle = NULL; | |
620 g_static_mutex_unlock(&mutex); | |
621 continue; | |
622 /* WSA_IO_PENDING indicates successful async notification will happen */ | |
623 } else if (errorid != WSA_IO_PENDING) { | |
624 gchar *msg = g_win32_error_message(errorid); | |
625 purple_timeout_add(0, _print_debug_msg, | |
626 g_strdup_printf("Unable to wait for changes. Message: %s (%d).\n", | |
627 msg, errorid)); | |
628 g_free(msg); | |
629 } | |
568 } | 630 } |
569 | 631 |
570 /* Make sure at least 30 seconds have elapsed since the last | 632 /* Make sure at least 30 seconds have elapsed since the last |
571 * notification so we don't peg the cpu if this keeps changing. */ | 633 * notification so we don't peg the cpu if this keeps changing. */ |
572 if ((time(NULL) - last_trigger) < 30) | 634 if ((time(NULL) - last_trigger) < 30) |
573 Sleep(30000); | 635 Sleep(30000); |
574 | 636 |
637 /* This will block until NLA notifies us */ | |
638 retval = WaitForSingleObjectEx(nla_event, WSA_INFINITE, TRUE); | |
639 | |
575 last_trigger = time(NULL); | 640 last_trigger = time(NULL); |
576 | 641 |
577 /* This will block until there is a network change */ | 642 g_static_mutex_lock(&mutex); |
578 if (MyWSANSPIoctl(h, SIO_NSP_NOTIFY_CHANGE, NULL, 0, NULL, 0, &retLen, NULL) == SOCKET_ERROR) { | 643 if (network_initialized == FALSE) { |
579 int errorid = WSAGetLastError(); | 644 /* Time to die */ |
580 gchar *msg = g_win32_error_message(errorid); | 645 WSACloseEvent(nla_event); |
581 purple_debug_warning("network", "Unable to wait for changes. Message: %s (%d).\n", | 646 g_static_mutex_unlock(&mutex); |
582 msg, errorid); | 647 g_thread_exit(NULL); |
583 g_free(msg); | 648 return NULL; |
584 } | 649 } |
585 | 650 |
586 retval = WSALookupServiceEnd(h); | 651 size = sizeof(buf); |
652 while ((retval = WSALookupServiceNext(network_change_handle, 0, &size, res)) == ERROR_SUCCESS) { | |
653 /*purple_timeout_add(0, _print_debug_msg, | |
654 g_strdup_printf("thread found network '%s'\n", | |
655 res->lpszServiceInstanceName ? res->lpszServiceInstanceName : "(NULL)"));*/ | |
656 size = sizeof(buf); | |
657 } | |
658 | |
659 WSAResetEvent(nla_event); | |
660 g_static_mutex_unlock(&mutex); | |
587 | 661 |
588 purple_timeout_add(0, wpurple_network_change_thread_cb, NULL); | 662 purple_timeout_add(0, wpurple_network_change_thread_cb, NULL); |
589 | |
590 } | 663 } |
591 | 664 |
592 g_thread_exit(NULL); | 665 g_thread_exit(NULL); |
593 return NULL; | 666 return NULL; |
594 } | 667 } |
712 #endif | 785 #endif |
713 #ifdef _WIN32 | 786 #ifdef _WIN32 |
714 GError *err = NULL; | 787 GError *err = NULL; |
715 gint cnt = wpurple_get_connected_network_count(); | 788 gint cnt = wpurple_get_connected_network_count(); |
716 | 789 |
790 network_initialized = TRUE; | |
717 if (cnt < 0) /* Assume there is a network */ | 791 if (cnt < 0) /* Assume there is a network */ |
718 current_network_count = 1; | 792 current_network_count = 1; |
719 /* Don't listen for network changes if we can't tell anyway */ | 793 /* Don't listen for network changes if we can't tell anyway */ |
720 else | 794 else { |
721 { | |
722 current_network_count = cnt; | 795 current_network_count = cnt; |
723 if (!g_thread_create(wpurple_network_change_thread, NULL, FALSE, &err)) | 796 if ((MyWSANSPIoctl = (void*) wpurple_find_and_loadproc("ws2_32.dll", "WSANSPIoctl"))) { |
724 purple_debug_error("network", "Couldn't create Network Monitor thread: %s\n", err ? err->message : ""); | 797 if (!g_thread_create(wpurple_network_change_thread, NULL, FALSE, &err)) |
798 purple_debug_error("network", "Couldn't create Network Monitor thread: %s\n", err ? err->message : ""); | |
799 } | |
725 } | 800 } |
726 #endif | 801 #endif |
727 | 802 |
728 purple_prefs_add_none ("/purple/network"); | 803 purple_prefs_add_none ("/purple/network"); |
729 purple_prefs_add_bool ("/purple/network/auto_ip", TRUE); | 804 purple_prefs_add_bool ("/purple/network/auto_ip", TRUE); |
780 } | 855 } |
781 if (nm_conn) | 856 if (nm_conn) |
782 dbus_g_connection_unref(nm_conn); | 857 dbus_g_connection_unref(nm_conn); |
783 #endif | 858 #endif |
784 | 859 |
860 #ifdef _WIN32 | |
861 g_static_mutex_lock(&mutex); | |
862 network_initialized = FALSE; | |
863 if (network_change_handle != NULL) { | |
864 int retval; | |
865 /* Trigger the NLA thread to stop waiting for network changes. Not | |
866 * doing this can cause hangs on WSACleanup. */ | |
867 purple_debug_warning("network", "Terminating the NLA thread\n"); | |
868 if ((retval = WSALookupServiceEnd(network_change_handle)) == SOCKET_ERROR) { | |
869 int errorid = WSAGetLastError(); | |
870 gchar *msg = g_win32_error_message(errorid); | |
871 purple_debug_warning("network", "Unable to kill NLA thread. Message: %s (%d).\n", | |
872 msg, errorid); | |
873 g_free(msg); | |
874 } | |
875 network_change_handle = NULL; | |
876 | |
877 } | |
878 g_static_mutex_unlock(&mutex); | |
879 | |
880 #endif | |
785 purple_signal_unregister(purple_network_get_handle(), | 881 purple_signal_unregister(purple_network_get_handle(), |
786 "network-configuration-changed"); | 882 "network-configuration-changed"); |
787 } | 883 } |