Mercurial > hg > nnchat
comparison nnchat.c @ 13:86fe5f0d1a85
Cleanups; Added probing connection (requesting some policy crap) to emulate the official client.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Mon, 24 Mar 2008 08:02:05 +0000 |
parents | df23968f0c6a |
children | 50d8396e7417 |
comparison
equal
deleted
inserted
replaced
12:df23968f0c6a | 13:86fe5f0d1a85 |
---|---|
42 { 1, 'v', "verbose", "Be more verbose", OPT_NONE }, | 42 { 1, 'v', "verbose", "Be more verbose", OPT_NONE }, |
43 { 2, 'p', "port", "Connect to port", OPT_ARGREQ }, | 43 { 2, 'p', "port", "Connect to port", OPT_ARGREQ }, |
44 { 3, 's', "server", "Server to connect to", OPT_ARGREQ }, | 44 { 3, 's', "server", "Server to connect to", OPT_ARGREQ }, |
45 { 4, 'C', "color", "Initial color in RGB hex 000000", OPT_ARGREQ }, | 45 { 4, 'C', "color", "Initial color in RGB hex 000000", OPT_ARGREQ }, |
46 { 5, 'l', "logfile", "Log filename", OPT_ARGREQ }, | 46 { 5, 'l', "logfile", "Log filename", OPT_ARGREQ }, |
47 /* | |
48 { 6, 'p', "plaintext", "Use plaintext logging", OPT_NONE }, | |
49 */ | |
50 }; | 47 }; |
51 | 48 |
52 const int optListN = (sizeof(optList) / sizeof(optarg_t)); | 49 const int optListN = (sizeof(optList) / sizeof(optarg_t)); |
53 | 50 |
54 | 51 |
482 if (!strncmp(str, "FAILURE", 7)) { | 479 if (!strncmp(str, "FAILURE", 7)) { |
483 printMsg("Login failure.\n"); | 480 printMsg("Login failure.\n"); |
484 return -2; | 481 return -2; |
485 } else if (!strncmp(str, "SUCCESS", 7)) { | 482 } else if (!strncmp(str, "SUCCESS", 7)) { |
486 printMsg("Login success.\n"); | 483 printMsg("Login success.\n"); |
487 sendUserMsg(sock, optUserName2, "%%2FSetFontColor%%20%%2Dcolor%%20%06X", optUserColor); | 484 sendUserMsg(sock, optUserName2, "%%2FRequestUserList"); |
488 return 0; | 485 return 0; |
489 } else | 486 } else |
490 return 1; | 487 return 1; |
491 } | 488 } |
492 | 489 |
619 return -1; | 616 return -1; |
620 } | 617 } |
621 } | 618 } |
622 | 619 |
623 | 620 |
621 int openConnection(struct in_addr *addr, int port) | |
622 { | |
623 struct sockaddr_in tmpAddr; | |
624 int sock = -1; | |
625 | |
626 tmpAddr.sin_family = AF_INET; | |
627 tmpAddr.sin_port = htons(port); | |
628 tmpAddr.sin_addr = *addr; | |
629 | |
630 THMSG(1, "Connecting to %s:%d ...\n", | |
631 inet_ntoa(tmpAddr.sin_addr), port); | |
632 | |
633 if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == -1) { | |
634 THERR("Could not open socket: %s\n", strerror(errno)); | |
635 return -2; | |
636 } | |
637 | |
638 THMSG(2, "Using socket %d.\n", sock); | |
639 | |
640 if (connect(sock, (struct sockaddr *) &tmpAddr, sizeof(tmpAddr)) == -1) { | |
641 THERR("Could not connect: %s\n", strerror(errno)); | |
642 return -5; | |
643 } | |
644 | |
645 return sock; | |
646 } | |
647 | |
648 | |
649 void closeConnection(int sock) | |
650 { | |
651 if (sock >= 0) { | |
652 #ifdef __WIN32 | |
653 closesocket(sock); | |
654 #else | |
655 close(sock); | |
656 #endif | |
657 } | |
658 } | |
659 | |
660 | |
624 int main(int argc, char *argv[]) | 661 int main(int argc, char *argv[]) |
625 { | 662 { |
626 int tmpSocket; | 663 int tmpSocket; |
627 struct hostent *tmpHost; | 664 struct hostent *tmpHost; |
628 struct sockaddr_in tmpAddr; | 665 BOOL exitProg = FALSE, colorSet = FALSE; |
629 BOOL exitProg = FALSE; | 666 struct timeval tv; |
667 fd_set sockfds; | |
668 fd_set inputfds; | |
669 char *tmpStr; | |
630 | 670 |
631 /* Initialize */ | 671 /* Initialize */ |
632 th_init("NNChat", "Newbie Nudes chat client", "0.3", | 672 th_init("NNChat", "Newbie Nudes chat client", "0.3", |
633 "Written and designed by Anonymous Finnish Guy (C) 2008", | 673 "Written and designed by Anonymous Finnish Guy (C) 2008", |
634 "This software is freeware, use and distribute as you wish."); | 674 "This software is freeware, use and distribute as you wish."); |
672 hstrerror(h_errno)); | 712 hstrerror(h_errno)); |
673 return -3; | 713 return -3; |
674 } | 714 } |
675 THMSG(2, "True hostname: %s\n", tmpHost->h_name); | 715 THMSG(2, "True hostname: %s\n", tmpHost->h_name); |
676 | 716 |
677 tmpAddr.sin_family = AF_INET; | 717 /* To emulate the official client, we first make a fake connection ... */ |
678 tmpAddr.sin_port = htons(optPort); | 718 if ((tmpSocket = openConnection((struct in_addr *) tmpHost->h_addr, optPort)) < 0) { |
679 tmpAddr.sin_addr = *((struct in_addr *) tmpHost->h_addr); | 719 THERR("Fakeprobe connection setup failed!\n"); |
680 | 720 goto err_exit; |
681 THMSG(1, "Connecting to %s:%d ...\n", | 721 } |
682 inet_ntoa(tmpAddr.sin_addr), optPort); | 722 |
683 | 723 tmpStr = "<policy-file-request/>"; |
684 if ((tmpSocket = socket(PF_INET, SOCK_STREAM, 0)) == -1) { | 724 if (sendToSocket(tmpSocket, tmpStr, strlen(tmpStr) + 1) < 0) { |
685 THERR("Could not open socket: %s\n", strerror(errno)); | 725 THERR("Failed to send fakeprobe.\n"); |
686 return -2; | 726 goto err_exit; |
687 } | 727 } else { |
688 | 728 ssize_t gotBuf; |
689 THMSG(2, "Using socket %d.\n", tmpSocket); | 729 char tmpBuf[4096]; |
690 | 730 gotBuf = recv(tmpSocket, tmpBuf, sizeof(tmpBuf), 0); |
691 if (connect(tmpSocket, (struct sockaddr *) &tmpAddr, sizeof(tmpAddr)) == -1) { | 731 tmpBuf[gotBuf-1] = 0; |
692 THERR("Could not connect: %s\n", strerror(errno)); | 732 THMSG(2, "Probe got: %s\n", tmpBuf); |
693 return -5; | 733 closeConnection(tmpSocket); |
694 } | 734 } |
695 | 735 |
736 /* Okay, now do the proper connection ... */ | |
737 if ((tmpSocket = openConnection((struct in_addr *) tmpHost->h_addr, optPort)) < 0) { | |
738 THERR("Main connection setup failed!\n"); | |
739 goto err_exit; | |
740 } | |
741 | |
696 THMSG(1, "Connected, logging in as '%s'.\n", optUserName); | 742 THMSG(1, "Connected, logging in as '%s'.\n", optUserName); |
697 optUserName2 = encodeStr1(optUserName); | 743 optUserName2 = encodeStr1(optUserName); |
698 | 744 |
699 sendUserMsg(tmpSocket, optUserName2, "%%2Flogin%%20%%2Dsite%%20NN%%20%%2Dpassword%%20%s", optPassword); | 745 sendUserMsg(tmpSocket, optUserName2, "%%2Flogin%%20%%2Dsite%%20NN%%20%%2Dpassword%%20%s", optPassword); |
700 | 746 |
701 struct timeval tv; | |
702 fd_set sockfds; | |
703 fd_set inputfds; | |
704 | |
705 | |
706 FD_ZERO(&inputfds); | 747 FD_ZERO(&inputfds); |
707 FD_SET(0, &inputfds); | 748 FD_SET(0, &inputfds); |
708 | |
709 FD_ZERO(&sockfds); | 749 FD_ZERO(&sockfds); |
710 FD_SET(tmpSocket, &sockfds); | 750 FD_SET(tmpSocket, &sockfds); |
711 | 751 |
712 while (!exitProg) { | 752 while (!exitProg) { |
713 ssize_t gotBuf; | 753 ssize_t gotBuf; |
769 exitProg = TRUE; | 809 exitProg = TRUE; |
770 } | 810 } |
771 } | 811 } |
772 } | 812 } |
773 | 813 |
814 if (!colorSet) { | |
815 colorSet = TRUE; | |
816 sendUserMsg(tmpSocket, optUserName2, "%%2FSetFontColor%%20%%2Dcolor%%20%06X", optUserColor); | |
817 } | |
818 | |
774 fflush(stdout); | 819 fflush(stdout); |
775 fflush(stderr); | 820 fflush(stderr); |
776 } | 821 } |
777 | 822 |
778 /* .. */ | 823 /* Shotdiwn */ |
824 err_exit: | |
779 th_free(optUserName2); | 825 th_free(optUserName2); |
780 | 826 |
827 closeConnection(tmpSocket); | |
828 | |
781 #ifdef __WIN32 | 829 #ifdef __WIN32 |
782 closesocket(tmpSocket); | |
783 WSACleanup(); | 830 WSACleanup(); |
784 #else | |
785 close(tmpSocket); | |
786 #endif | 831 #endif |
832 | |
833 THMSG(1, "Connection terminated.\n"); | |
787 | 834 |
788 if (optLogFile) { | 835 if (optLogFile) { |
789 THMSG(1, "Closing logfile.\n"); | 836 THMSG(1, "Closing logfile.\n"); |
790 fclose(optLogFile); | 837 fclose(optLogFile); |
791 } | 838 } |
792 | 839 |
793 THMSG(1, "Connection terminated.\n"); | |
794 | 840 |
795 return 0; | 841 return 0; |
796 } | 842 } |