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 }