├── .sconsign.dblite ├── LICENSE.GPL ├── README.rst ├── Sconstruct ├── TODO ├── base64.c ├── base64.h ├── bdgfun.c ├── bdgmsg.h ├── bdgstep.c ├── bin ├── ISSUE! └── tknet.info ├── bkgd.c ├── bkgd.h ├── comdef.h ├── doc ├── Bdg main steps.jpg ├── GetLastErr.code ├── List.png ├── NAT relay.png └── how to get NAT type.png ├── head.h ├── history ├── tknet 2012-04-04 09-55-23m.zip └── tknet 2012-07-06 21-40-54m.zip ├── keyinfo.c ├── keyinfo.h ├── list.c ├── list.h ├── main.c ├── nat_checkd.c ├── nat_checkd.h ├── nattype.c ├── nattype.h ├── netaddr.h ├── netproc.c ├── netproc.h ├── peerdata.c ├── peerdata.h ├── pipe.c ├── pipe.h ├── popmail.c ├── popmail.h ├── relay.c ├── relay.h ├── session.c ├── session.h ├── smtpmail.c ├── smtpmail.h ├── sock.c ├── sock.h ├── stun.c ├── stun.h ├── sysi.c ├── sysi.h ├── test ├── bin │ ├── dir0 │ │ └── tknet.info │ ├── dir1 │ │ └── tknet.info │ ├── dir2 │ │ └── tknet.info │ └── dir3 │ │ └── tknet.info ├── demo.c ├── demos │ ├── bkgd-demo.c │ ├── keyinfo-demo.c │ ├── list-demo.c │ ├── most-simple-UDP-demo.c │ ├── nattype-demo.c │ ├── netproc-demo.c │ ├── peerdata-demo.c │ ├── pipe-demo.c │ ├── popmail-demo.c │ ├── smtpmail-demo.c │ ├── sock-demo.c │ ├── treap-demo.c │ └── tree-demo.c ├── screenshots │ ├── NAT type0.png │ └── NAT type3.png ├── unit.out └── unit_test.c ├── tknet.h ├── tknet.sh ├── treap.c ├── treap.h ├── tree.c └── tree.h /.sconsign.dblite: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w32zhong/tknet/77d7810abcfdc7cd7bbe556a922fbd7fac37b7a7/.sconsign.dblite -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | Notice 2 | ======= 3 | This repo is a very early experiment of my idea, and is not active now because lack of participation and most importantly, author decides to focus on more practical project (this project relies on Email server, which is only practical in a small scale deployment). If you still think this is useful, send an issue to me and I would also like to help as always. 4 | 5 | INTRO: 6 | ====== 7 | tknet is designed to become a simple cross-platform P2P library. 8 | 9 | tknet uses traditional centralized-server-based model, however, different from other P2P solutions, tknet peer is able to use Email server to track center servers (namely bridge peers or BDG peers) when necessary. It uses a private protocol and is still under development. Despite these, it works and it is simple. 10 | 11 | I simply include how to build it in this README and have not written documents before I think it is at least usable and easy-to-use. If you are interested in this project, please let me know! I need some incentive to let tknet go further. 12 | 13 | BUILD: 14 | ====== 15 | STEP 1: 16 | ~~~~~~ 17 | Scons(see http://www.scons.org/) is required for building, OpenSSL-dev library is also needed if you want to enable SSL feature. 18 | 19 | STEP 2: 20 | ~~~~~~ 21 | Run the './tknet.sh build' command in the source directory, an executable demo program and the tknet binary library are created under ./bin folder. 22 | 23 | LICENSE: 24 | ======== 25 | tknet source code is used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE.GPL included in the packaging of this file. Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: 26 | 27 | http://www.gnu.org/copyleft/gpl.html 28 | 29 | CONTACT: 30 | ======== 31 | Feel free to contact me via clock126@126.com. 32 | -------------------------------------------------------------------------------- /Sconstruct: -------------------------------------------------------------------------------- 1 | Library('libtknet',Glob('./*.c'),LIBS=['mcheck','ssl','crypto','dl','pthread'],CCFLAGS = '-Wall -Werror=return-type'); 2 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | *********************************************************************** 2 | This file lists what functions and ideas worth adding into the project. 3 | *********************************************************************** 4 | Currently most important: 5 | use an efficient software interruption to replace polling(tree 21342%2) 6 | 7 | Others: 8 | add re-send & circle-buffer utilities. 9 | the ability to update tknet program at remote.(md5 check) 10 | classify prompts into 'debug' and 'important'. 11 | speed up connection further. 12 | config (which to print -- file name, line number at head is a good idea, log or give to a callback function) and (which do not) using a new config file. 13 | graphical and statistical debug ability. 14 | an idea to implement a command-based interface with only one string parameter for each function. 15 | a well designed error code model applied system wide. 16 | a similar interface with that of vvnet. 17 | a note that a connection maybe still connected when session is prompting the end. 18 | the ability to call another proc in one proc. 19 | 20 | A large-scale usable version further needs these features: 21 | enable BDG server to be relayer and even STUN server. 22 | SSL in POP3 process. 23 | encrypted config file 24 | encrypted BDG process 25 | -------------------------------------------------------------------------------- /base64.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | #include "base64.h" 15 | 16 | void 17 | Base64Encode(char *src, int src_len, char *dst) 18 | { 19 | int i = 0, j = 0; 20 | char base64_map[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 21 | 22 | for (; i < src_len - src_len % 3; i += 3) 23 | { 24 | dst[j++] = base64_map[(src[i] >> 2) & 0x3F]; 25 | dst[j++] = base64_map[((src[i] << 4) & 0x30) + ((src[i + 1] >> 4) & 0xF)]; 26 | dst[j++] = base64_map[((src[i + 1] << 2) & 0x3C) + ((src[i + 2] >> 6) & 0x3)]; 27 | dst[j++] = base64_map[src[i + 2] & 0x3F]; 28 | } 29 | 30 | if (src_len % 3 == 1) 31 | { 32 | dst[j++] = base64_map[(src[i] >> 2) & 0x3F]; 33 | dst[j++] = base64_map[(src[i] << 4) & 0x30]; 34 | dst[j++] = '='; 35 | dst[j++] = '='; 36 | } 37 | else if (src_len % 3 == 2) 38 | { 39 | dst[j++] = base64_map[(src[i] >> 2) & 0x3F]; 40 | dst[j++] = base64_map[((src[i] << 4) & 0x30) + ((src[i + 1] >> 4) & 0xF)]; 41 | dst[j++] = base64_map[(src[i + 1] << 2) & 0x3C]; 42 | dst[j++] = '='; 43 | } 44 | 45 | dst[j] = '\0'; 46 | } 47 | 48 | -------------------------------------------------------------------------------- /base64.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | void 15 | Base64Encode(char *src, int src_len, char *dst); 16 | // dst and src must be different buffer. 17 | -------------------------------------------------------------------------------- /bdgfun.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | #include "tknet.h" 15 | 16 | DEF_STRUCT_CONSTRUCTOR( Peer , 17 | out_cons->addr.IPv4 = 0; 18 | out_cons->addr.port = 0; 19 | out_cons->NATType = NAT_T_UNKNOWN; 20 | strcpy(out_cons->NameID,"NO Name"); 21 | ) 22 | 23 | DEF_STRUCT_CONSTRUCTOR( BridgeProc , 24 | out_cons->pPeerDataRoot = NULL; 25 | out_cons->pSeedPeerCache = NULL; 26 | ProcessCons(&out_cons->proc); 27 | out_cons->pSock = NULL; 28 | out_cons->pProcList = NULL; 29 | out_cons->Else = NULL; 30 | 31 | PeerCons(&out_cons->s); 32 | PeerCons(&out_cons->a); 33 | PeerCons(&out_cons->b); 34 | PeerCons(&out_cons->sx); 35 | ) 36 | 37 | static struct BridgeProc sta_BdgSubServerProc; 38 | 39 | CONNECT_CALLBK g_ConnectionNotify = NULL; 40 | 41 | static void 42 | BdgClientProcNotify(struct Process *pa_) 43 | { 44 | struct BridgeProc *pProc = GET_STRUCT_ADDR(pa_ , struct BridgeProc , proc); 45 | DEF_AND_CAST(pBCPPa,struct BridgeClientProcPa,pProc->Else); 46 | 47 | PROMPT(Usual,"Client proc end:\n"); 48 | ProcessTraceSteps(pa_); 49 | PROMPT(Usual,"\n"); 50 | 51 | //NEVER free the client proc in the main loop 52 | //instead, we set the ifConnected flag and free client 53 | //proc by FreeBdgClientProc() after loop. 54 | pBCPPa->ifConnected = 0; 55 | } 56 | 57 | void 58 | BdgSubServerProcNotify(struct Process *pa_) 59 | { 60 | struct BridgeProc *pBdgProc = GET_STRUCT_ADDR(pa_ , struct BridgeProc , proc); 61 | struct PeerData *pPD = GET_STRUCT_ADDR(pBdgProc,struct PeerData,BdgProc); 62 | 63 | PROMPT(Usual,"Sub Server proc end:\n"); 64 | ProcessTraceSteps(pa_); 65 | PROMPT(Usual,"\n"); 66 | PeerDataDele(pPD,pBdgProc->pSeedPeerCache); 67 | } 68 | 69 | struct PeerData* 70 | NewPeerDataWithBdgProc(struct NetAddr pa_addr,uchar pa_NATType,char *pa_pName,struct BridgeProc *pa_pBdgProc) 71 | { 72 | struct PeerData *pPD = tkmalloc(struct PeerData); 73 | PeerDataCons(pPD); 74 | 75 | pPD->addr = pa_addr; 76 | pPD->NATType = pa_NATType; 77 | strcpy(pPD->NameID,pa_pName); 78 | 79 | pPD->BdgProc.pPeerDataRoot = pa_pBdgProc->pPeerDataRoot; 80 | pPD->BdgProc.pSeedPeerCache = pa_pBdgProc->pSeedPeerCache; 81 | pPD->BdgProc.pSock = pa_pBdgProc->pSock; 82 | pPD->BdgProc.pProcList = pa_pBdgProc->pProcList; 83 | 84 | ProcessConsAndSetSteps(&(pPD->BdgProc.proc), &sta_BdgSubServerProc.proc ); 85 | pPD->BdgProc.proc.NotifyCallbk = &BdgSubServerProcNotify; 86 | 87 | return pPD; 88 | } 89 | 90 | void 91 | SetPeerByPeerData(struct Peer *pa_pPeer,struct PeerData *pa_pPD) 92 | { 93 | strcpy(pa_pPeer->NameID,pa_pPD->NameID); 94 | pa_pPeer->addr = pa_pPD->addr; 95 | pa_pPeer->NATType = pa_pPD->NATType; 96 | } 97 | 98 | void 99 | FreeBridgeServer(struct BridgeProc *pa_pBdgProc) 100 | { 101 | ProcessFree(&pa_pBdgProc->proc); 102 | } 103 | 104 | void 105 | FreeSubBridgeServerTemplate() 106 | { 107 | ProcessFree(&sta_BdgSubServerProc.proc); 108 | } 109 | 110 | struct BridgeMsg* 111 | BdgMsgRead(struct Process *in_proc , uchar pa_option , uchar pa_msg , struct NetAddr *pa_pAddr) 112 | { 113 | struct BridgeProc *pBdgProc = GET_STRUCT_ADDR(in_proc,struct BridgeProc,proc); 114 | struct NetAddr FromAddr = GetAddrFromSockAddr(&pBdgProc->pSock->AddrRecvfrom); 115 | DEF_AND_CAST(pMsg,struct TkNetMsg,pBdgProc->pSock->RecvBuff); 116 | DEF_AND_CAST(pBdgMsg,struct BridgeMsg,&(pMsg->msg.BdgMsg)); 117 | 118 | if( pMsg->flag != TK_NET_BDG_MSG_FLAG || 119 | pBdgProc->pSock->RecvLen <= 0 ) 120 | { 121 | return NULL; 122 | } 123 | else if( pa_option == BDG_READ_OPT_ANY ) 124 | { 125 | return pBdgMsg; 126 | } 127 | else if( pa_option == BDG_READ_OPT_ADDR_FILTER && 128 | ifNetAddrEqual(&FromAddr,pa_pAddr) ) 129 | { 130 | return pBdgMsg; 131 | } 132 | else if( pa_option == BDG_READ_OPT_MSG_FILTER && 133 | pBdgMsg->info == pa_msg ) 134 | { 135 | return pBdgMsg; 136 | } 137 | else 138 | { 139 | return NULL; 140 | } 141 | } 142 | 143 | void 144 | BdgMsgWrite(struct Process *in_proc ,struct BridgeMsg *in_msg , struct NetAddr *pa_pAddr) 145 | { 146 | struct BridgeProc *pBdgProc = GET_STRUCT_ADDR(in_proc,struct BridgeProc,proc); 147 | struct TkNetMsg SendingMsg; 148 | 149 | SendingMsg.flag = TK_NET_BDG_MSG_FLAG; 150 | SendingMsg.msg.BdgMsg = *in_msg; 151 | 152 | SockLocateTa(pBdgProc->pSock,htonl(pa_pAddr->IPv4),pa_pAddr->port); 153 | SockWrite(pBdgProc->pSock,BYS(SendingMsg)); 154 | } 155 | 156 | void 157 | ConsAndStartBridgeServer(struct BridgeProc *pa_pBdgProc , struct PeerData *pa_pPeerDataRoot , struct ProcessingList *pa_pProcList , struct Sock *pa_pMainSock , struct Iterator *pa_pSeedPeerCache) 158 | { 159 | BdgSubServerProcInit(); 160 | BridgeProcCons(pa_pBdgProc); 161 | pa_pBdgProc->pPeerDataRoot = pa_pPeerDataRoot; 162 | pa_pBdgProc->pSeedPeerCache = pa_pSeedPeerCache; 163 | pa_pBdgProc->pSock = pa_pMainSock; 164 | pa_pBdgProc->pProcList = pa_pProcList; 165 | 166 | PROCESS_ADD_STEP( &pa_pBdgProc->proc , BridgeMain , g_WaitLevel[4] ); 167 | ProcessStart( &pa_pBdgProc->proc , pa_pProcList ); 168 | } 169 | 170 | void 171 | BridgeClientTryBdgServerProc(struct BridgeProc *pa_pBdgProc,struct BridgeHelloStepPa *pa_pProcPa , struct Sock *pa_pMainSock) 172 | { 173 | BridgeProcCons(pa_pBdgProc); 174 | pa_pBdgProc->pSock = pa_pMainSock; 175 | pa_pBdgProc->Else = pa_pProcPa; 176 | PROCESS_ADD_STEP( &pa_pBdgProc->proc , BdgClientTryBdgServer , g_WaitLevel[2] ); 177 | } 178 | 179 | void 180 | FreeBdgClientProc(struct BridgeProc *pa_pBdgProc) 181 | { 182 | ProcessFree(&pa_pBdgProc->proc); 183 | if(pa_pBdgProc->Else) 184 | tkfree(pa_pBdgProc->Else); 185 | } 186 | 187 | void 188 | BdgSubServerProcInit() 189 | { 190 | ProcessCons(&sta_BdgSubServerProc.proc); 191 | PROCESS_ADD_STEP( &sta_BdgSubServerProc.proc , BdgBeginSubServer , g_WaitLevel[2]); 192 | PROCESS_ADD_STEP( &sta_BdgSubServerProc.proc , BdgConnectRequireServer ,g_WaitLevel[3]); 193 | PROCESS_ADD_STEP( &sta_BdgSubServerProc.proc , BdgConnectRequireReply , g_WaitLevel[2]); 194 | PROCESS_ADD_STEP( &sta_BdgSubServerProc.proc , BdgConnectDecision , g_WaitLevel[2] ); 195 | PROCESS_ADD_STEP( &sta_BdgSubServerProc.proc , BdgPunchingServer , g_WaitLevel[2] ); 196 | PROCESS_ADD_STEP( &sta_BdgSubServerProc.proc , BdgConnectAddrServer , g_WaitLevel[2] ); 197 | PROCESS_ADD_STEP( &sta_BdgSubServerProc.proc , BdgErrReturnServer , g_WaitLevel[2] ); 198 | } 199 | 200 | 201 | struct BridgeClientProcPa* 202 | BridgeMakeClientProc(struct BridgeProc *pa_pBdgProc, struct Sock *pa_pMainSock , 203 | struct ProcessingList *pa_pProcList,struct NetAddr *pa_pAddr, 204 | char *pa_pMyNameID ,uchar pa_MyNatType , 205 | const char **pa_ppTargetNameID , BOOL pa_ifSkipRegister) 206 | //TaName can be NULL 207 | { 208 | struct BridgeClientProcPa *pBCPPa = tkmalloc(struct BridgeClientProcPa); 209 | 210 | BridgeProcCons(pa_pBdgProc); 211 | 212 | pa_pBdgProc->pSock = pa_pMainSock; 213 | pa_pBdgProc->pProcList = pa_pProcList; 214 | pa_pBdgProc->s.addr = *pa_pAddr; 215 | pa_pBdgProc->a.NATType = pa_MyNatType; 216 | pa_pBdgProc->Else = pBCPPa;//Give a extra struct to client process 217 | pa_pBdgProc->proc.NotifyCallbk = &BdgClientProcNotify; 218 | 219 | pBCPPa->pMyNameID = pa_pMyNameID; 220 | pBCPPa->ppTargetNameID = pa_ppTargetNameID; 221 | pBCPPa->DirectConnectAddr.IPv4 = 0; 222 | pBCPPa->DirectConnectAddr.port = 0; 223 | pBCPPa->ifSkipRegister = pa_ifSkipRegister; 224 | pBCPPa->ifFastSendWait = 0; 225 | pBCPPa->ifConnected = 0; 226 | 227 | if(!pa_ifSkipRegister) 228 | { 229 | PROCESS_ADD_STEP( &pa_pBdgProc->proc , BdgClientRegister , g_WaitLevel[2] ); 230 | } 231 | PROCESS_ADD_STEP( &pa_pBdgProc->proc , BdgClientWait , g_WaitLevel[3] ); 232 | PROCESS_ADD_STEP( &pa_pBdgProc->proc , BdgClientConnectRequire , g_WaitLevel[2] ); 233 | PROCESS_ADD_STEP( &pa_pBdgProc->proc , BdgClientDoConnectAddr , g_WaitLevel[2] ); 234 | PROCESS_ADD_STEP( &pa_pBdgProc->proc , BdgClientMultiSendNotify , g_WaitLevel[0] ); 235 | 236 | return pBCPPa; 237 | } 238 | -------------------------------------------------------------------------------- /bdgmsg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | #define PEER_NAME_ID_LEN 16 15 | 16 | #define TK_NET_DATA_LEN 128 17 | 18 | #define TK_NET_BDG_MSG_FLAG 0 19 | 20 | #define BDG_READ_OPT_ANY 0 21 | #define BDG_READ_OPT_ADDR_FILTER 1 22 | #define BDG_READ_OPT_MSG_FILTER 2 23 | 24 | #define BRIDGE_MSG_INFO_UNKNOWN 0 25 | 26 | #define BRIDGE_MSG_INFO_HELLO_BDG 1 27 | #define BRIDGE_MSG_INFO_IAM_HERE 2 28 | 29 | #define BRIDGE_MSG_INFO_REGISTER 3 30 | #define BRIDGE_MSG_ERR_NAMEID_EXIST 4 31 | #define BRIDGE_MSG_INFO_RGST_OK 5 32 | 33 | #define BRIDGE_MSG_INFO_WAITING 6 34 | #define BRIDGE_MSG_INFO_ECHO 7 35 | 36 | #define BRIDGE_MSG_INFO_CONNECT 8 37 | #define BRIDGE_MSG_INFO_CONNECT_BEGIN 9 38 | #define BRIDGE_MSG_ERR_NO_NAMEID 10 39 | 40 | #define BRIDGE_MSG_INFO_PUNCHING 11 41 | #define BRIDGE_MSG_INFO_PUNCHING_FINISH 12 42 | 43 | #define BRIDGE_MSG_INFO_CONNECT_ADDR 13 44 | #define BRIDGE_MSG_ERR_CONNECT_ADDR 14 45 | 46 | #define BRIDGE_MSG_INFO_HELLO 15 47 | #define BRIDGE_MSG_INFO_ESTABLISHED 16 48 | 49 | #define BRIDGE_MSG_ERR_NO_SEED_TO_RELAY 17 50 | #define BRIDGE_MSG_ERR_ERROR 18 51 | #define BRIDGE_MSG_INFO_ACKNOWLEDGE 19 52 | 53 | #define BRIDGE_MSG_INFO_WAIT_RELAY 20 54 | 55 | #define CONNECT_DECISION_FLAG_BEGIN 1 56 | #define CONNECT_DECISION_FLAG_DIRECT 2 57 | #define CONNECT_DECISION_FLAG_ERR 3 58 | #define CONNECT_DECISION_FLAG_A_SIDE_RELAY 4 59 | #define CONNECT_DECISION_FLAG_B_SIDE_RELAY 5 60 | 61 | struct BridgeHelloStepPa 62 | { 63 | BOOL res; 64 | struct NetAddr addr; 65 | }; 66 | 67 | struct BridgeClientProcPa 68 | { 69 | char *pMyNameID; 70 | const char **ppTargetNameID; 71 | struct NetAddr DirectConnectAddr; 72 | BOOL ifSkipRegister; 73 | BOOL ifFastSendWait;//everytime client go to send "waiting" 74 | //message letting server begain the connection decision, 75 | //it is too slow. We use this flag to let client send immediately 76 | //after he returns to the wait step. 77 | BOOL ifConnected;//if server client are disconnected for some reasons, 78 | //we set this flag to zero, then the main loop will know this situation, 79 | //and may try to connect another server. 80 | }; 81 | 82 | struct Peer 83 | { 84 | char NameID[PEER_NAME_ID_LEN]; 85 | struct NetAddr addr; 86 | uchar NATType; 87 | }; 88 | 89 | struct BridgeProc 90 | { 91 | struct PeerData *pPeerDataRoot; 92 | struct Iterator *pSeedPeerCache; 93 | struct Process proc; 94 | struct Sock *pSock; 95 | struct ProcessingList *pProcList; 96 | struct Peer s,a,b,sx; 97 | uint DecisionRelayID; 98 | uchar DecisionFlag; 99 | struct NetAddr DecisionPunAddr,DecisionConAddr; 100 | char PunAddrNameID[PEER_NAME_ID_LEN]; 101 | char ConAddrNameID[PEER_NAME_ID_LEN]; 102 | struct NetAddr addr; 103 | struct NetAddr MultiSendTo; 104 | uchar MultiSendInfo; 105 | uchar ErrCode; 106 | void *Else; 107 | }; 108 | 109 | struct BridgeMsg 110 | { 111 | uchar info; 112 | struct NetAddr addr; 113 | uint RelayID; 114 | char NameID[PEER_NAME_ID_LEN]; 115 | uchar NATType; 116 | uchar Relays; 117 | uchar ErrCode; 118 | }; 119 | 120 | struct TkNetMsg 121 | { 122 | uchar flag; 123 | ushort UsrDatLen;//Only used when msg union stands for UsrDat 124 | //(flag is not TK_NET_BDG_MSG_FLAG). 125 | union 126 | { 127 | struct BridgeMsg BdgMsg; 128 | char UsrDat[TK_NET_DATA_LEN]; 129 | }msg; 130 | }; 131 | 132 | DECLARATION_STRUCT_CONSTRUCTOR( BridgeProc ) 133 | DECLARATION_STRUCT_CONSTRUCTOR( Peer ) 134 | 135 | void 136 | ConsAndStartBridgeServer(struct BridgeProc * , struct PeerData * , 137 | struct ProcessingList * , struct Sock *,struct Iterator *); 138 | 139 | void 140 | FreeBridgeServer(struct BridgeProc *); 141 | 142 | void 143 | FreeSubBridgeServerTemplate(); 144 | 145 | void 146 | BridgeClientTryBdgServerProc(struct BridgeProc *,struct BridgeHelloStepPa * , struct Sock *); 147 | 148 | struct BridgeClientProcPa* 149 | BridgeMakeClientProc(struct BridgeProc *, struct Sock *,struct ProcessingList *, 150 | struct NetAddr *, char * ,uchar , const char** ,BOOL); 151 | 152 | void 153 | FreeBdgClientProc(struct BridgeProc *); 154 | 155 | void 156 | SetPeerByPeerData(struct Peer *,struct PeerData *); 157 | 158 | #define BDG_ADDR( _name , _p_bdg_proc ) \ 159 | &( _p_bdg_proc-> _name .addr ) 160 | 161 | #define IF_NEAD_RELAY( _NAT0 , _NAT1 ) ( _NAT0 + _NAT1 >= 5) 162 | 163 | struct BridgeMsg* 164 | BdgMsgRead(struct Process * , uchar , uchar , struct NetAddr *); 165 | 166 | void 167 | BdgMsgWrite(struct Process * ,struct BridgeMsg * , struct NetAddr *); 168 | 169 | struct PeerData* 170 | NewPeerDataWithBdgProc(struct NetAddr ,uchar ,char *,struct BridgeProc *); 171 | 172 | void 173 | BdgSubServerProcInit(); 174 | 175 | EXTERN_STEP( BdgClientTryBdgServer ) 176 | 177 | EXTERN_STEP( BridgeMain ) 178 | EXTERN_STEP( BdgBeginSubServer ) 179 | EXTERN_STEP( BdgConnectRequireServer ) 180 | EXTERN_STEP( BdgConnectRequireReply ) 181 | EXTERN_STEP( BdgConnectDecision ) 182 | EXTERN_STEP( BdgPunchingServer ) 183 | EXTERN_STEP( BdgConnectAddrServer ) 184 | EXTERN_STEP( BdgErrReturnServer ) 185 | 186 | EXTERN_STEP( BdgClientRegister ) 187 | EXTERN_STEP( BdgClientWait ) 188 | EXTERN_STEP( BdgClientConnectRequire ) 189 | EXTERN_STEP( BdgClientDoConnectAddr ) 190 | EXTERN_STEP( BdgClientMultiSendNotify ) 191 | 192 | typedef void (*CONNECT_CALLBK)(struct NetAddr,struct Sock*,struct ProcessingList*, 193 | struct Iterator*,struct Iterator*); 194 | 195 | extern CONNECT_CALLBK g_ConnectionNotify; 196 | 197 | #define ON_CONNECT() \ 198 | OnConnect(struct NetAddr pa_addr,struct Sock *pa_pSock,struct ProcessingList *pa_pProcList \ 199 | ,struct Iterator* pa_pINow,struct Iterator *pa_pIForward) 200 | 201 | static __inline void 202 | PeerTrace( struct Peer *pa_pPeer ) 203 | { 204 | char AddrText[32]; 205 | GetAddrText(&pa_pPeer->addr,AddrText); 206 | PROMPT(Usual,"%s(%s)",pa_pPeer->NameID,AddrText); 207 | } 208 | 209 | static __inline void 210 | BetweenMacro( struct Peer *pa_pPeer0, struct Peer *pa_pPeer1 ) 211 | { 212 | PROMPT(Usual,"between "); 213 | PeerTrace( pa_pPeer0 ); 214 | PROMPT(Usual," and "); 215 | PeerTrace( pa_pPeer1 ); 216 | PROMPT(Usual," . \n"); 217 | } 218 | -------------------------------------------------------------------------------- /bin/ISSUE!: -------------------------------------------------------------------------------- 1 | build: 2013-11-15 23:19:47-05:00 2 | Set tknet condition: 1 3 | level0: 600*2 4 | level1: 1500*2 5 | level2: 2000*2 6 | level3: 9000*2 7 | level4: 20000*2 8 | level5: 1800000*1 9 | using config: port 8912,named BDG. 10 | target name unset. 11 | stun proc:208.97.25.20/3478. 12 | Binding request to 208.97.25.20/3478.. 13 | CHANGED-ADDRESS attribute recved 14 | CHANGED-ADDRESS attribute recved 15 | recv STUN from 208.97.25.20/3478 ,saying that my public address is 76.124.91.219 16 | /8912 and 'change address' is 208.97.25.12/3479 17 | Sending ChangeIPAndPort request to 208.97.25.20/3478 .. 18 | Sending ChangeIPAndPort request to 208.97.25.20/3478 .. 19 | Sending ChangeIPAndPort request to 208.97.25.20/3478 .. 20 | Binding request to server #2(208.97.25.12/3478).. 21 | CHANGED-ADDRESS attribute recved 22 | CHANGED-ADDRESS attribute recved 23 | recv STUN from 208.97.25.12/3478 ,saying that my public address is 76.124.91.219 24 | /8912 25 | Sending ChangePort request to 208.97.25.20/3478 .. 26 | CHANGED-ADDRESS attribute recved 27 | CHANGED-ADDRESS attribute recved 28 | recv STUN from 208.97.25.20/3479 29 | KeyInfo Stun proc end. 30 | NAT type got from STUN. 31 | NAT type: 1 (restricted cone) 32 | 33 | stun proc:208.97.25.20/3478. 34 | Binding request to 208.97.25.20/3478.. 35 | CHANGED-ADDRESS attribute recved 36 | CHANGED-ADDRESS attribute recved 37 | recv STUN from 208.97.25.20/3478 ,saying that my public address is 76.124.91.219 38 | /8912 and 'change address' is 208.97.25.12/3479 39 | Sending ChangeIPAndPort request to 208.97.25.20/3478 .. 40 | CHANGED-ADDRESS attribute recved 41 | CHANGED-ADDRESS attribute recved 42 | recv STUN from 208.97.25.12/3479 43 | Binding request to server #2(208.97.25.12/3478).. 44 | CHANGED-ADDRESS attribute recved 45 | CHANGED-ADDRESS attribute recved 46 | recv STUN from 208.97.25.12/3478 ,saying that my public address is 76.124.91.219 47 | /8912 48 | KeyInfo Stun proc end. 49 | NAT type got from STUN. 50 | NAT type: 0 (full cone) 51 | 52 | stun proc:208.97.25.20/3478. 53 | Binding request to 208.97.25.20/3478.. 54 | CHANGED-ADDRESS attribute recved 55 | CHANGED-ADDRESS attribute recved 56 | recv STUN from 208.97.25.20/3478 ,saying that my public address is 76.124.91.219 57 | /8912 and 'change address' is 208.97.25.12/3479 58 | Sending ChangeIPAndPort request to 208.97.25.20/3478 .. 59 | CHANGED-ADDRESS attribute recved 60 | CHANGED-ADDRESS attribute recved 61 | recv STUN from 208.97.25.12/3479 62 | Binding request to server #2(208.97.25.12/3478).. 63 | CHANGED-ADDRESS attribute recved 64 | CHANGED-ADDRESS attribute recved 65 | recv STUN from 208.97.25.12/3478 ,saying that my public address is 76.124.91.219 66 | /8912 67 | KeyInfo Stun proc end. 68 | NAT type got from STUN. 69 | NAT type: 0 (full cone) 70 | NAT type double checked. 71 | -------------------------------------------------------------------------------- /bin/tknet.info: -------------------------------------------------------------------------------- 1 | Config 127.0.0.1 8912 WAN BDG StdinToCmd 2 | MailServer 220.181.12.101 110 0 li28jhyxy76223 g131517 3 | SMTPServer 123.58.178.204 25 0 li28jhyxy76223 g131517 li28jhyxy76223@163.com 4 | # stun.stunprotocol.org (107.23.150.92) 5 | STUNServer 107.23.150.92 3478 6 | # stun.ideasip.com (208.97.25.20) 7 | STUNServer 208.97.25.20 3478 8 | -------------------------------------------------------------------------------- /bkgd.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | #define BKGD_CMD_MAX_LEN 128 14 | 15 | extern BOOL g_ifStdinToCmd; 16 | extern tkMutex g_BkgdMutex; 17 | extern TK_THREAD( BackGround ); 18 | extern char g_TargetName[]; 19 | extern struct NetAddr g_BdgPeerAddr; 20 | extern uchar g_BkgdNatTestRes; 21 | extern struct NetAddr g_BkgdNatTestAddrRes; 22 | 23 | struct BackGroundArgs 24 | { 25 | struct KeyInfoCache *pInfoCache; 26 | struct ProcessingList *pProcList; 27 | struct PeerData *pPeerDataRoot; 28 | struct BridgeProc *pBdgClientProc; 29 | struct Sock *pMainSock; 30 | struct CheckNATProc *pCheckNATProc; 31 | }; 32 | 33 | BOOL 34 | ifBkgdStunProc(); 35 | 36 | BOOL 37 | ifBkgdSubProcess(); 38 | -------------------------------------------------------------------------------- /comdef.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | #ifndef NULL 15 | #define NULL 0 16 | #endif 17 | 18 | #ifndef BOOL 19 | #define BOOL int 20 | #endif 21 | 22 | typedef unsigned int uint; 23 | typedef unsigned short ushort; 24 | typedef unsigned char uchar; 25 | 26 | #define DEF_STRUCT_CONSTRUCTOR( _type_name , _assignments ) \ 27 | void \ 28 | _type_name ## Cons( struct _type_name * out_cons) \ 29 | { \ 30 | _assignments \ 31 | } 32 | 33 | #define DECLARATION_STRUCT_CONSTRUCTOR( _type_name ) \ 34 | void _type_name ## Cons( struct _type_name * ); 35 | 36 | #define DEF_AND_CAST( _to_var , _type_tag_casting_to , _from_var ) \ 37 | _type_tag_casting_to * _to_var = ( _type_tag_casting_to *)( _from_var ) 38 | 39 | #define MEMBER_OFFSET( _type_tag , _member ) (uintptr_t)(&( (( _type_tag *)0)-> _member )) 40 | 41 | #define GET_STRUCT_ADDR( _member_addr , _type_tag , _member_name ) \ 42 | ( _type_tag *)((uintptr_t)( _member_addr ) - MEMBER_OFFSET( _type_tag , _member_name ) ) 43 | 44 | #define TK_EXCEPTION( _describe ) \ 45 | _descr_exception_( __FILE__ ": " #_describe " exception at line " \ 46 | , __LINE__ ) 47 | 48 | static __inline void 49 | _descr_exception_(const char* pa_presay ,uint pa_l) 50 | { 51 | char LineBuff[16]; 52 | tkLog(0,pa_presay); 53 | tkFormatStr(LineBuff,"%d",pa_l); 54 | tkLog(0,LineBuff); 55 | tkLog(0,".\n"); 56 | } 57 | 58 | #define VCK( _cdt , _statments ) \ 59 | if( _cdt ) \ 60 | { \ 61 | TK_EXCEPTION( _cdt ); \ 62 | _statments ; \ 63 | }do{}while(0) 64 | 65 | 66 | struct Bys 67 | { 68 | const char* pBytes; 69 | uint len; 70 | }; 71 | 72 | #define BYS( _obj ) _Bys( (char*)& ( _obj ) , sizeof( _obj ) ) 73 | 74 | #define SHORT_SLEEP_INTERVAL 20 75 | 76 | static __inline struct Bys 77 | _Bys( char* pa_p , uint pa_size ) 78 | { 79 | struct Bys res; 80 | res.pBytes = pa_p; 81 | res.len = pa_size; 82 | 83 | return res; 84 | 85 | } 86 | 87 | static __inline struct Bys 88 | StrBys(const char* in_str) 89 | { 90 | struct Bys res; 91 | res.pBytes = in_str; 92 | res.len = strlen(in_str); 93 | 94 | return res; 95 | } 96 | -------------------------------------------------------------------------------- /doc/Bdg main steps.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w32zhong/tknet/77d7810abcfdc7cd7bbe556a922fbd7fac37b7a7/doc/Bdg main steps.jpg -------------------------------------------------------------------------------- /doc/GetLastErr.code: -------------------------------------------------------------------------------- 1 | /usr/include/asm-generic/errno.h 2 | 3 | #define EDEADLK 35 /* Resource deadlock would occur */ 4 | #define ENAMETOOLONG 36 /* File name too long */ 5 | #define ENOLCK 37 /* No record locks available */ 6 | #define ENOSYS 38 /* Function not implemented */ 7 | #define ENOTEMPTY 39 /* Directory not empty */ 8 | #define ELOOP 40 /* Too many symbolic links encountered */ 9 | #define EWOULDBLOCK EAGAIN /* Operation would block */ 10 | #define ENOMSG 42 /* No message of desired type */ 11 | #define EIDRM 43 /* Identifier removed */ 12 | #define ECHRNG 44 /* Channel number out of range */ 13 | #define EL2NSYNC 45 /* Level 2 not synchronized */ 14 | #define EL3HLT 46 /* Level 3 halted */ 15 | #define EL3RST 47 /* Level 3 reset */ 16 | #define ELNRNG 48 /* Link number out of range */ 17 | #define EUNATCH 49 /* Protocol driver not attached */ 18 | #define ENOCSI 50 /* No CSI structure available */ 19 | #define EL2HLT 51 /* Level 2 halted */ 20 | #define EBADE 52 /* Invalid exchange */ 21 | #define EBADR 53 /* Invalid request descriptor */ 22 | #define EXFULL 54 /* Exchange full */ 23 | #define ENOANO 55 /* No anode */ 24 | #define EBADRQC 56 /* Invalid request code */ 25 | #define EBADSLT 57 /* Invalid slot */ 26 | 27 | #define EDEADLOCK EDEADLK 28 | 29 | #define EBFONT 59 /* Bad font file format */ 30 | #define ENOSTR 60 /* Device not a stream */ 31 | #define ENODATA 61 /* No data available */ 32 | #define ETIME 62 /* Timer expired */ 33 | #define ENOSR 63 /* Out of streams resources */ 34 | #define ENONET 64 /* Machine is not on the network */ 35 | #define ENOPKG 65 /* Package not installed */ 36 | #define EREMOTE 66 /* Object is remote */ 37 | #define ENOLINK 67 /* Link has been severed */ 38 | #define EADV 68 /* Advertise error */ 39 | #define ESRMNT 69 /* Srmount error */ 40 | #define ECOMM 70 /* Communication error on send */ 41 | #define EPROTO 71 /* Protocol error */ 42 | #define EMULTIHOP 72 /* Multihop attempted */ 43 | #define EDOTDOT 73 /* RFS specific error */ 44 | #define EBADMSG 74 /* Not a data message */ 45 | #define EOVERFLOW 75 /* Value too large for defined data type */ 46 | #define ENOTUNIQ 76 /* Name not unique on network */ 47 | #define EBADFD 77 /* File descriptor in bad state */ 48 | #define EREMCHG 78 /* Remote address changed */ 49 | #define ELIBACC 79 /* Can not access a needed shared library */ 50 | #define ELIBBAD 80 /* Accessing a corrupted shared library */ 51 | #define ELIBSCN 81 /* .lib section in a.out corrupted */ 52 | #define ELIBMAX 82 /* Attempting to link in too many shared libraries */ 53 | #define ELIBEXEC 83 /* Cannot exec a shared library directly */ 54 | #define EILSEQ 84 /* Illegal byte sequence */ 55 | #define ERESTART 85 /* Interrupted system call should be restarted */ 56 | #define ESTRPIPE 86 /* Streams pipe error */ 57 | #define EUSERS 87 /* Too many users */ 58 | #define ENOTSOCK 88 /* Socket operation on non-socket */ 59 | #define EDESTADDRREQ 89 /* Destination address required */ 60 | #define EMSGSIZE 90 /* Message too long */ 61 | #define EPROTOTYPE 91 /* Protocol wrong type for socket */ 62 | #define ENOPROTOOPT 92 /* Protocol not available */ 63 | #define EPROTONOSUPPORT 93 /* Protocol not supported */ 64 | #define ESOCKTNOSUPPORT 94 /* Socket type not supported */ 65 | #define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ 66 | #define EPFNOSUPPORT 96 /* Protocol family not supported */ 67 | #define EAFNOSUPPORT 97 /* Address family not supported by protocol */ 68 | #define EADDRINUSE 98 /* Address already in use */ 69 | #define EADDRNOTAVAIL 99 /* Cannot assign requested address */ 70 | #define ENETDOWN 100 /* Network is down */ 71 | #define ENETUNREACH 101 /* Network is unreachable */ 72 | #define ENETRESET 102 /* Network dropped connection because of reset */ 73 | #define ECONNABORTED 103 /* Software caused connection abort */ 74 | #define ECONNRESET 104 /* Connection reset by peer */ 75 | #define ENOBUFS 105 /* No buffer space available */ 76 | #define EISCONN 106 /* Transport endpoint is already connected */ 77 | #define ENOTCONN 107 /* Transport endpoint is not connected */ 78 | #define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ 79 | #define ETOOMANYREFS 109 /* Too many references: cannot splice */ 80 | #define ETIMEDOUT 110 /* Connection timed out */ 81 | #define ECONNREFUSED 111 /* Connection refused */ 82 | #define EHOSTDOWN 112 /* Host is down */ 83 | #define EHOSTUNREACH 113 /* No route to host */ 84 | #define EALREADY 114 /* Operation already in progress */ 85 | #define EINPROGRESS 115 /* Operation now in progress */ 86 | #define ESTALE 116 /* Stale NFS file handle */ 87 | #define EUCLEAN 117 /* Structure needs cleaning */ 88 | #define ENOTNAM 118 /* Not a XENIX named type file */ 89 | #define ENAVAIL 119 /* No XENIX semaphores available */ 90 | #define EISNAM 120 /* Is a named type file */ 91 | #define EREMOTEIO 121 /* Remote I/O error */ 92 | #define EDQUOT 122 /* Quota exceeded */ 93 | 94 | #define ENOMEDIUM 123 /* No medium found */ 95 | #define EMEDIUMTYPE 124 /* Wrong medium type */ 96 | #define ECANCELED 125 /* Operation Canceled */ 97 | #define ENOKEY 126 /* Required key not available */ 98 | #define EKEYEXPIRED 127 /* Key has expired */ 99 | #define EKEYREVOKED 128 /* Key has been revoked */ 100 | #define EKEYREJECTED 129 /* Key was rejected by service */ 101 | 102 | /* for robust mutexes */ 103 | #define EOWNERDEAD 130 /* Owner died */ 104 | #define ENOTRECOVERABLE 131 /* State not recoverable */ 105 | 106 | #define ERFKILL 132 /* Operation not possible due to RF-kill */ 107 | -------------------------------------------------------------------------------- /doc/List.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w32zhong/tknet/77d7810abcfdc7cd7bbe556a922fbd7fac37b7a7/doc/List.png -------------------------------------------------------------------------------- /doc/NAT relay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w32zhong/tknet/77d7810abcfdc7cd7bbe556a922fbd7fac37b7a7/doc/NAT relay.png -------------------------------------------------------------------------------- /doc/how to get NAT type.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w32zhong/tknet/77d7810abcfdc7cd7bbe556a922fbd7fac37b7a7/doc/how to get NAT type.png -------------------------------------------------------------------------------- /head.h: -------------------------------------------------------------------------------- 1 | #define TKNET_VER "2013-11-15 23:19:47-05:00" 2 | -------------------------------------------------------------------------------- /history/tknet 2012-04-04 09-55-23m.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w32zhong/tknet/77d7810abcfdc7cd7bbe556a922fbd7fac37b7a7/history/tknet 2012-04-04 09-55-23m.zip -------------------------------------------------------------------------------- /history/tknet 2012-07-06 21-40-54m.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w32zhong/tknet/77d7810abcfdc7cd7bbe556a922fbd7fac37b7a7/history/tknet 2012-07-06 21-40-54m.zip -------------------------------------------------------------------------------- /keyinfo.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | #define KEY_INFO_MAX_LEN MAX_MAIL_CONTENT_LEN 15 | 16 | #define KEY_INFO_TYPE_CONFIG 0x00 17 | #define KEY_INFO_TYPE_MAILSERVER 0x01 18 | #define KEY_INFO_TYPE_BRIDGEPEER 0x02 19 | #define KEY_INFO_TYPE_STUNSERVER 0x03 20 | #define KEY_INFO_TYPE_SMTPSERVER 0x04 21 | 22 | #define KEY_INFO_VALID_UNSURE 0x04 23 | #define KEY_INFO_VALID_NOT 0x05 24 | #define KEY_INFO_VALID_WORKS 0x06 25 | 26 | struct KeyInfoCache 27 | { 28 | int KeyInfoNumbers; 29 | struct Iterator IKeyInfo; 30 | }; 31 | 32 | struct KeyInfo 33 | { 34 | int num; 35 | uchar valid; 36 | uchar type; 37 | char text[KEY_INFO_MAX_LEN]; 38 | struct NetAddr addr; 39 | struct ListNode ln; 40 | }; 41 | 42 | uchar 43 | KeyInfoReadFile( struct KeyInfoCache * , const char * ); 44 | 45 | void 46 | KeyInfoWriteFile( struct KeyInfoCache * , const char * ); 47 | 48 | void 49 | KeyInfoTrace( struct KeyInfoCache * ); 50 | 51 | void 52 | KeyInfoFree(struct KeyInfoCache *); 53 | 54 | void 55 | KeyInfoWorksFine( struct KeyInfoCache * , int ); 56 | 57 | struct KeyInfo* 58 | KeyInfoFindByType( struct KeyInfoCache *, uchar ); 59 | //different from KeyInfoSelectA() which takes 'valide' into consideration, 60 | //this function only use type as filter. 61 | 62 | void 63 | KeyInfoUpdate( struct KeyInfoCache * ); 64 | 65 | BOOL 66 | KeyInfoUse( struct KeyInfo * , struct KeyInfoCache * , struct Sock* ); 67 | 68 | BOOL 69 | KeyInfoTry(struct KeyInfoCache * , uchar , struct Sock* ); 70 | 71 | BOOL 72 | KeyInfoDoubleCheckNAT(struct KeyInfoCache *, struct Sock *); 73 | 74 | char* 75 | GetNextSeparateStr(char ** ); 76 | 77 | struct KeyInfo* 78 | NewKeyInfoFromStrLine(char *); 79 | 80 | struct KeyInfo* 81 | KeyInfoInsert(struct KeyInfo *,struct KeyInfoCache *); 82 | //insert a key info, if a same address info existed, return it. 83 | 84 | void 85 | KeyInfoDele(struct KeyInfo *,struct KeyInfoCache *); 86 | 87 | DECLARATION_STRUCT_CONSTRUCTOR( KeyInfoCache ) 88 | 89 | struct FindKeyInfoByTypePa 90 | { 91 | uchar TypeToFind; 92 | struct KeyInfo *found; 93 | }; 94 | 95 | struct FindKeyInfoByNumPa 96 | { 97 | int NumToFind; 98 | struct KeyInfo *found; 99 | }; 100 | 101 | struct FindKeyInfoByValidPa 102 | { 103 | uchar valid; 104 | struct KeyInfo *found; 105 | }; 106 | 107 | struct FindKeyInfoByAddrPa 108 | { 109 | struct NetAddr addr; 110 | struct KeyInfo *found; 111 | }; 112 | 113 | BOOL 114 | LIST_ITERATION_CALLBACK_FUNCTION(FindKeyInfoByNum); 115 | 116 | BOOL 117 | LIST_ITERATION_CALLBACK_FUNCTION(FindKeyInfoByValid); 118 | 119 | BOOL 120 | LIST_ITERATION_CALLBACK_FUNCTION(FindKeyInfoByAddr); 121 | 122 | extern char g_TargetName[]; 123 | extern char g_MyName[]; 124 | extern BOOL g_ifConfigAsFullCone; 125 | -------------------------------------------------------------------------------- /list.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | #include "tknet.h" 15 | 16 | DEF_STRUCT_CONSTRUCTOR( ListNode , 17 | out_cons->next = out_cons; 18 | out_cons->last = out_cons; 19 | ) 20 | 21 | struct Iterator 22 | GetIterator(struct ListNode* in_node) 23 | { 24 | struct Iterator i; 25 | 26 | if(in_node == NULL) 27 | { 28 | i.now = i.last = NULL; 29 | } 30 | else 31 | { 32 | i.now = in_node; 33 | i.last = in_node->last; 34 | } 35 | 36 | return i; 37 | } 38 | 39 | void 40 | tk(struct Iterator* i0 ,struct Iterator* i1) 41 | { 42 | if(i0->now == NULL) 43 | { 44 | *i0 = *i1; 45 | } 46 | else if(i1->now == NULL) 47 | { 48 | *i1 = *i0; 49 | } 50 | 51 | i0->now->last = i1->last; 52 | i0->last->next = i1->now; 53 | 54 | i1->now->last = i0->last; 55 | i1->last->next = i0->now; 56 | 57 | i0->last = i1->last; 58 | i1->last = i1->now->last; 59 | } 60 | 61 | void 62 | AddOneToListTail(struct Iterator* io_IHead , struct ListNode* in_NodeOfAdding ) 63 | { 64 | struct Iterator IAdd = GetIterator( in_NodeOfAdding ); 65 | tk( io_IHead , &IAdd ); 66 | } 67 | 68 | void 69 | AddOneToListHead(struct Iterator* io_IHead , struct ListNode* in_NodeOfAdding ) 70 | { 71 | AddOneToListTail( io_IHead , in_NodeOfAdding ); 72 | *io_IHead = GetIterator( io_IHead->last ); 73 | } 74 | 75 | void 76 | AddOneToListTailSafe(struct Iterator* pa_pIHead, struct Iterator* pa_pINow , struct Iterator* pa_pIForward , struct ListNode* in_NodeOfAdding ) 77 | { 78 | AddOneToListTail(pa_pIHead,in_NodeOfAdding); 79 | 80 | *pa_pINow = GetIterator(pa_pINow->now); 81 | *pa_pIForward = GetIterator(pa_pINow->now->next); 82 | } 83 | 84 | void 85 | AddOneToListHeadSafe(struct Iterator* pa_pIHead, struct Iterator* pa_pINow , struct Iterator* pa_pIForward , struct ListNode* in_NodeOfAdding ) 86 | { 87 | AddOneToListTailSafe( pa_pIHead , pa_pINow , pa_pIForward , in_NodeOfAdding ); 88 | *pa_pIHead = GetIterator( pa_pIHead->last ); 89 | } 90 | 91 | BOOL 92 | ListDragOneOut(struct Iterator *pa_pIHead,struct ListNode *pa_pNode) 93 | { 94 | struct Iterator INow = GetIterator(pa_pNode); 95 | struct Iterator IForward = GetIterator(pa_pNode->next); 96 | struct Iterator *pa_pINow = &INow, *pa_pIForward = &IForward; 97 | 98 | tk(pa_pINow,pa_pIForward); 99 | LIST_SAFE_RETURN; 100 | } 101 | 102 | void 103 | ForEach(struct Iterator* io_IHead , ListNodeCallBack pa_node_callback ,void* pa_else ) 104 | { 105 | struct Iterator INow; 106 | struct Iterator IForward; 107 | INow = *io_IHead; 108 | 109 | if(io_IHead->now == NULL) 110 | { 111 | return; 112 | } 113 | 114 | while(1) 115 | { 116 | IForward = GetIterator( INow.now->next ); 117 | 118 | if( pa_node_callback( io_IHead , &INow , &IForward , pa_else ) ) 119 | { 120 | break; 121 | } 122 | 123 | INow = IForward; 124 | } 125 | } 126 | 127 | BOOL 128 | LIST_ITERATION_CALLBACK_FUNCTION( SortingInsert ) 129 | { 130 | DEF_AND_CAST(pSip , struct SortingInsertPa , pa_else); 131 | 132 | if( pSip->si_cbk(pSip->pIInsert, pa_pINow , pSip->else_pa) ) 133 | { 134 | tk(pSip->pIInsert , pa_pINow); 135 | 136 | if(pa_pINow->now == pa_pIHead->now) 137 | { 138 | *pa_pIHead = *(pSip->pIInsert); 139 | } 140 | 141 | return 1; 142 | 143 | } 144 | else if(pa_pINow->now == pa_pIHead->last) 145 | { 146 | tk(pSip->pIInsert,pa_pIHead); 147 | 148 | return 1; 149 | } 150 | else 151 | { 152 | return 0; 153 | } 154 | } 155 | 156 | struct SortListCallbackPa 157 | { 158 | struct Iterator* pNewList; 159 | struct SortingInsertPa* pSip; 160 | }; 161 | 162 | static BOOL 163 | LIST_ITERATION_CALLBACK_FUNCTION(SortListCallback) 164 | { 165 | DEF_AND_CAST(pSlcbp , struct SortListCallbackPa , pa_else); 166 | tk( pa_pINow , pa_pIForward ); 167 | 168 | if(pSlcbp->pNewList->now == NULL) 169 | { 170 | tk( pa_pINow , pSlcbp->pNewList ); 171 | } 172 | else 173 | { 174 | pSlcbp->pSip->pIInsert = pa_pINow; 175 | ForEach( pSlcbp->pNewList , &SortingInsert , pSlcbp->pSip ); 176 | } 177 | 178 | return pa_pINow->now == pa_pIHead->last; 179 | } 180 | 181 | void 182 | SortList( struct Iterator* io_IHead , struct SortingInsertPa* in_sip) 183 | { 184 | struct Iterator INewList = GetIterator(NULL); 185 | struct SortListCallbackPa slcbp; 186 | slcbp.pNewList = &INewList; 187 | slcbp.pSip = in_sip; 188 | 189 | ForEach( io_IHead , &SortListCallback , &slcbp ); 190 | *io_IHead = INewList; 191 | } 192 | 193 | static BOOL 194 | LIST_ITERATION_CALLBACK_FUNCTION(ReverseListCallback) 195 | { 196 | DEF_AND_CAST( pNewList , struct Iterator , pa_else ); 197 | 198 | tk( pa_pINow , pa_pIForward ); 199 | tk( pa_pINow , pNewList ); 200 | *pNewList = *pa_pINow; 201 | 202 | return pa_pINow->now == pa_pIHead->last; 203 | } 204 | 205 | void 206 | ReverseList( struct Iterator* io_IHead) 207 | { 208 | struct Iterator INewList = GetIterator(NULL); 209 | 210 | ForEach( io_IHead , &ReverseListCallback , &INewList); 211 | *io_IHead = INewList; 212 | } 213 | -------------------------------------------------------------------------------- /list.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | #define GET_STRUCT_ADDR_FROM_IT( _iterator , _type_tag , _list_node_member_name ) \ 15 | ( _type_tag *)((uintptr_t)( ( _iterator )->now) - MEMBER_OFFSET( _type_tag , _list_node_member_name ) ) 16 | 17 | #define LIST_ITERATION_CALLBACK_FUNCTION( _fun_name ) \ 18 | _fun_name (struct Iterator* pa_pIHead, struct Iterator* pa_pINow , struct Iterator* pa_pIForward , void* pa_else) 19 | 20 | #define DEF_FREE_LIST_ELEMENT_CALLBACK_FUNCTION( _fun_name , _type_tag , _list_node_member_name , _other_statements ) \ 21 | BOOL \ 22 | LIST_ITERATION_CALLBACK_FUNCTION( _fun_name ) \ 23 | { \ 24 | _type_tag * pNow = GET_STRUCT_ADDR_FROM_IT( pa_pINow , _type_tag , _list_node_member_name ); \ 25 | _other_statements \ 26 | tk( pa_pINow , pa_pIForward ); \ 27 | tkfree(pNow); \ 28 | if( pa_pINow->now == pa_pIHead->last ) \ 29 | { \ 30 | *pa_pIHead = GetIterator( NULL ); \ 31 | return 1; \ 32 | } else \ 33 | { \ 34 | return 0; \ 35 | } \ 36 | } 37 | 38 | #define LIST_SAFE_RETURN \ 39 | if( pa_pINow->now == pa_pIForward->last ) \ 40 | { \ 41 | *pa_pIHead = GetIterator( NULL ); \ 42 | return 1; \ 43 | } else \ 44 | { \ 45 | if( pa_pINow->now == pa_pIHead->now || \ 46 | pa_pINow->now == pa_pIHead->last ) \ 47 | { \ 48 | *pa_pIHead = *pa_pIForward; \ 49 | } \ 50 | return 0; \ 51 | }do{}while(0) 52 | 53 | #define DEF_FREE_LIST_ELEMENT_SAFE_FUNCTION( _fun_name , _type_tag , _list_node_member_name , _other_statements ) \ 54 | BOOL \ 55 | LIST_ITERATION_CALLBACK_FUNCTION( _fun_name ) \ 56 | { \ 57 | _type_tag * pNow = GET_STRUCT_ADDR_FROM_IT( pa_pINow , _type_tag , _list_node_member_name ); \ 58 | _other_statements \ 59 | tk( pa_pINow , pa_pIForward ); \ 60 | tkfree(pNow); \ 61 | LIST_SAFE_RETURN; \ 62 | } 63 | 64 | struct ListNode 65 | { 66 | struct ListNode *next,*last; 67 | }; 68 | 69 | DECLARATION_STRUCT_CONSTRUCTOR( ListNode ) 70 | 71 | struct Iterator 72 | { 73 | struct ListNode *now,*last; 74 | }; 75 | 76 | typedef BOOL (*SortingInsertCallBack)(struct Iterator*, struct Iterator* , void*); 77 | 78 | struct SortingInsertPa 79 | { 80 | SortingInsertCallBack si_cbk; 81 | struct Iterator* pIInsert; 82 | void* else_pa; 83 | }; 84 | 85 | typedef BOOL (*ListNodeCallBack)(struct Iterator* , struct Iterator* ,struct Iterator* ,void*); 86 | 87 | struct Iterator 88 | GetIterator(struct ListNode* ); 89 | 90 | void 91 | tk(struct Iterator* ,struct Iterator* ); 92 | 93 | void 94 | AddOneToListTail(struct Iterator* , struct ListNode* ); 95 | 96 | void 97 | AddOneToListHead(struct Iterator* , struct ListNode* ); 98 | 99 | void 100 | AddOneToListTailSafe(struct Iterator* , struct Iterator* , struct Iterator* , struct ListNode* ); 101 | 102 | void 103 | AddOneToListHeadSafe(struct Iterator* , struct Iterator* , struct Iterator* , struct ListNode* ); 104 | 105 | BOOL 106 | ListDragOneOut(struct Iterator *,struct ListNode *); 107 | 108 | void 109 | ForEach(struct Iterator* , ListNodeCallBack ,void* ); 110 | 111 | BOOL 112 | LIST_ITERATION_CALLBACK_FUNCTION( SortingInsert ); 113 | 114 | void 115 | SortList( struct Iterator* , struct SortingInsertPa* ); 116 | 117 | void 118 | ReverseList( struct Iterator* ); 119 | -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | #include "tknet.h" 15 | 16 | BOOL g_MainLoopFlag = 1; 17 | BOOL g_ifConfigAsFullCone = 0; 18 | struct NetAddr g_BdgPeerAddr; 19 | char g_TargetName[PEER_NAME_ID_LEN]; 20 | const char *g_pTargetName = NULL; 21 | char g_MyName[PEER_NAME_ID_LEN]; 22 | 23 | #define STDOUT_BUFFLEN (PROMT_BUFFERSIZE*3) 24 | static char sta_StdoutBuff[STDOUT_BUFFLEN]; 25 | static uint sta_StdoutBuffIndex = 0;//point to the first unfilled buffer. 26 | struct pipe *sta_pStdoutPipe = NULL; 27 | 28 | static 29 | FLOW_CALLBK_FUNCTION( StdoutFlowCallbk ) 30 | { 31 | uint i; 32 | 33 | for(i=0;i< pa_DataLen ;i++) 34 | { 35 | VCK(pa_pData[i] == '\0',continue); 36 | putchar(pa_pData[i]); 37 | } 38 | 39 | fflush(stdout); 40 | 41 | if(sta_StdoutBuffIndex + pa_DataLen > STDOUT_BUFFLEN) 42 | { 43 | memcpy(sta_StdoutBuff + sta_StdoutBuffIndex , 44 | pa_pData, STDOUT_BUFFLEN - sta_StdoutBuffIndex); 45 | sta_StdoutBuffIndex = STDOUT_BUFFLEN; 46 | 47 | StdoutPipeFlush(); 48 | } 49 | else 50 | { 51 | memcpy(sta_StdoutBuff + sta_StdoutBuffIndex , 52 | pa_pData, pa_DataLen); 53 | sta_StdoutBuffIndex += pa_DataLen; 54 | } 55 | } 56 | 57 | void 58 | StdoutPipeFlush() 59 | { 60 | if(NULL == sta_pStdoutPipe) 61 | sta_pStdoutPipe = PipeMap("stdout"); 62 | 63 | if(sta_StdoutBuffIndex == 0) 64 | return; 65 | else 66 | PipeFlow(sta_pStdoutPipe,sta_StdoutBuff,sta_StdoutBuffIndex,NULL); 67 | 68 | sta_StdoutBuffIndex = 0; 69 | } 70 | 71 | TK_THREAD( StdinThread ) 72 | { 73 | static char buff[BKGD_CMD_MAX_LEN]; 74 | DEF_AND_CAST(pPipe,struct pipe,pa_else); 75 | struct pipe *pFindPipe; 76 | 77 | while(g_MainLoopFlag) 78 | { 79 | fgets(buff,BKGD_CMD_MAX_LEN,stdin); 80 | 81 | if(!g_MainLoopFlag) 82 | break; 83 | //Main thread has exited, so break this thread too. 84 | 85 | MutexLock(&g_BkgdMutex); 86 | 87 | if(strcmp(buff,"control\n") == 0) 88 | { 89 | pFindPipe = PipeFindByName("cmd"); 90 | VCK(pFindPipe == NULL , goto unlock); 91 | PipeDirectOnlyTo(pPipe,pFindPipe); 92 | goto unlock; 93 | } 94 | 95 | PipeFlow(pPipe,buff,strlen(buff),NULL); 96 | //Do not flow '\0' in string pipe. 97 | unlock: 98 | MutexUnlock(&g_BkgdMutex); 99 | 100 | tkMsSleep(SHORT_SLEEP_INTERVAL); 101 | } 102 | 103 | return NULL; 104 | } 105 | 106 | static 107 | FLOW_CALLBK_FUNCTION( LogFlowCallbk ) 108 | { 109 | tkLogLenDat(1,(const char*)pa_pData, pa_DataLen); 110 | PipeFlow(pa_pPipe,pa_pData,pa_DataLen,NULL); 111 | } 112 | 113 | void 114 | tkNetDefaultPipeInit() 115 | { 116 | struct pipe *pPipe; 117 | 118 | pPipe = PipeMap("null"); 119 | 120 | pPipe = PipeMap("log"); 121 | pPipe->FlowCallbk = &LogFlowCallbk; 122 | 123 | pPipe = PipeMap("stdout"); 124 | pPipe->FlowCallbk = &StdoutFlowCallbk; 125 | 126 | pPipe = PipeMap("stdin"); 127 | tkBeginThread( &StdinThread , pPipe ); 128 | } 129 | 130 | void 131 | tkNetCommonInit() 132 | { 133 | MutexInit(&g_BkgdMutex); 134 | tkInitRandom(); 135 | tkLogInit(); 136 | SockInit(); 137 | 138 | PipeModuleInit(); 139 | tkNetDefaultPipeInit(); 140 | } 141 | 142 | void 143 | tkNetCommonUninit() 144 | { 145 | g_MainLoopFlag = 0; 146 | PipeModuleUninit(); 147 | SockDestory(); 148 | tkLogClose(); 149 | tkMsSleep(SHORT_SLEEP_INTERVAL);//waiting for threads 150 | MutexDelete(&g_BkgdMutex); 151 | } 152 | 153 | void 154 | tkNetConnect(const char *pa_pName) 155 | { 156 | if( pa_pName != NULL ) 157 | strcpy( g_TargetName , pa_pName ); 158 | 159 | g_pTargetName = pa_pName; 160 | } 161 | 162 | static void 163 | InitPipeStdoutDirection() 164 | { 165 | struct pipe *pPipe; 166 | g_pUsualPrompt = PipeMap((char*)g_UsualPromptName); 167 | pPipe = PipeFindByName("stdout"); 168 | 169 | if(pPipe) 170 | PipeDirectTo(g_pUsualPrompt,pPipe); 171 | else 172 | TK_EXCEPTION("stdout"); 173 | } 174 | 175 | int 176 | tkNetMain(int pa_argn,char **in_args) 177 | { 178 | struct KeyInfoCache KeyInfoCache; 179 | struct ProcessingList ProcList; 180 | struct BackGroundArgs BkgdArgs; 181 | struct PeerData PeerDataRoot; 182 | struct Iterator ISeedPeer; 183 | struct Sock MainSock; 184 | struct BridgeProc BdgServerProc; 185 | struct BridgeProc BdgClientProc; 186 | char BdgPeerAddrStr[32]; 187 | BOOL ifClientSkipRegister = 1; 188 | int TestPurposeNatType; 189 | struct BridgeClientProcPa *pBCPPa = NULL; 190 | 191 | g_TargetName[0]='\0'; 192 | g_MyName[0]='\0'; 193 | 194 | tkNetCommonInit(); 195 | InitPipeStdoutDirection(); 196 | 197 | PROMPT(Usual,"tknet \n build: " TKNET_VER "\n"); 198 | 199 | ProcessSetCondition(1); 200 | 201 | MkCmdModePipe(); 202 | MkChatModePipe(); 203 | 204 | ISeedPeer = GetIterator(NULL); 205 | 206 | PeerDataCons(&PeerDataRoot); 207 | PeerDataRoot.tpnd.RanPriority = 0; 208 | PeerDataRoot.addr.port = 0; 209 | PeerDataRoot.addr.IPv4 = 0; 210 | 211 | ProcessingListCons( &ProcList ); 212 | 213 | RelayModuleInit(); 214 | 215 | KeyInfoCacheCons(&KeyInfoCache); 216 | if(!KeyInfoReadFile(&KeyInfoCache,"tknet.info")) 217 | { 218 | PROMPT(Usual,"config file lost.\n"); 219 | goto exit; 220 | } 221 | 222 | if(!KeyInfoTry(&KeyInfoCache,KEY_INFO_TYPE_CONFIG,&MainSock)) 223 | { 224 | PROMPT(Usual,"bad config format.\n"); 225 | goto exit; 226 | } 227 | 228 | if( g_TargetName[0] != '\0' ) 229 | { 230 | PROMPT(Usual,"target name: %s \n", g_TargetName); 231 | tkNetConnect(g_TargetName); 232 | } 233 | else 234 | { 235 | PROMPT(Usual,"target name unset. \n"); 236 | } 237 | 238 | if(g_ifConfigAsFullCone) 239 | { 240 | g_NATtype = NAT_T_FULL_CONE; 241 | PROMPT(Usual,"config NAT type as fullcone.\n"); 242 | } 243 | else 244 | { 245 | while(!KeyInfoDoubleCheckNAT(&KeyInfoCache,&MainSock)) 246 | { 247 | if(!KeyInfoTry(&KeyInfoCache,KEY_INFO_TYPE_MAILSERVER,&MainSock)) 248 | { 249 | PROMPT(Usual,"No way to get NAT type.\n"); 250 | goto exit; 251 | } 252 | } 253 | 254 | PROMPT(Usual,"NAT type double checked.\n"); 255 | } 256 | 257 | if(pa_argn == 2) 258 | { 259 | sscanf(in_args[1],"%d",&TestPurposeNatType); 260 | g_NATtype = (uchar)TestPurposeNatType; 261 | 262 | PROMPT(Usual,"NAT type assigned by argument.\n"); 263 | NatTypePrint(g_NATtype); 264 | } 265 | 266 | while(!KeyInfoTry(&KeyInfoCache,KEY_INFO_TYPE_BRIDGEPEER,&MainSock)) 267 | { 268 | if(!KeyInfoTry(&KeyInfoCache,KEY_INFO_TYPE_MAILSERVER,&MainSock)) 269 | { 270 | PROMPT(Usual,"no avalible Bridge peer.\n"); 271 | tkNetConnect(NULL); 272 | 273 | if(g_NATtype == NAT_T_FULL_CONE && 0 == strcmp(g_MyName,"BDG")) 274 | { 275 | BkgdArgs.pCheckNATProc = 276 | CheckNATProcConsAndBegin(&ProcList, &KeyInfoCache); 277 | PROMPT(Usual,"This is BridgePeer.\n"); 278 | } 279 | 280 | goto no_bdg_peer; 281 | } 282 | } 283 | 284 | BkgdArgs.pCheckNATProc = NULL; 285 | GetAddrText(&g_BdgPeerAddr,BdgPeerAddrStr); 286 | PROMPT(Usual,"using Bridge peer: %s\n",BdgPeerAddrStr); 287 | ifClientSkipRegister = 0; 288 | 289 | no_bdg_peer: 290 | 291 | pBCPPa = BridgeMakeClientProc(&BdgClientProc,&MainSock,&ProcList,&g_BdgPeerAddr, 292 | g_MyName,g_NATtype,&g_pTargetName,ifClientSkipRegister); 293 | ProcessStart(&BdgClientProc.proc,&ProcList); 294 | 295 | if(g_ifStdinToCmd) 296 | PROMPT(Usual,"back ground enabled.\n"); 297 | else 298 | PROMPT(Usual,"back ground disabled.\n"); 299 | 300 | BkgdArgs.pPeerDataRoot = &PeerDataRoot; 301 | BkgdArgs.pInfoCache = &KeyInfoCache; 302 | BkgdArgs.pProcList = &ProcList; 303 | BkgdArgs.pBdgClientProc = &BdgClientProc; 304 | BkgdArgs.pMainSock = &MainSock; 305 | 306 | MutexLock(&g_BkgdMutex); 307 | tkBeginThread( &BackGround , &BkgdArgs ); 308 | 309 | PROMPT(Usual,"wait BackGround thread init...\n"); 310 | MutexLock(&g_BkgdMutex); 311 | MutexUnlock(&g_BkgdMutex); 312 | 313 | ConsAndStartBridgeServer(&BdgServerProc,&PeerDataRoot,&ProcList,&MainSock,&ISeedPeer); 314 | 315 | PROMPT(Usual,"tknet gets prepared.\n"); 316 | 317 | while( g_MainLoopFlag ) 318 | { 319 | MutexLock(&g_BkgdMutex); 320 | 321 | if(!ifBkgdStunProc()) 322 | SockRead(&MainSock); 323 | 324 | DoProcessing( &ProcList ); 325 | 326 | if(!ifBkgdStunProc()) 327 | MainSock.RecvLen = 0; 328 | 329 | StdoutPipeFlush(); 330 | 331 | MutexUnlock(&g_BkgdMutex); 332 | tkMsSleep(SHORT_SLEEP_INTERVAL); 333 | } 334 | 335 | ProcessDisattach(&BdgClientProc.proc,&ProcList); 336 | FreeBdgClientProc(&BdgClientProc); 337 | 338 | ProcessDisattach(&BdgServerProc.proc,&ProcList); 339 | FreeBridgeServer(&BdgServerProc); 340 | 341 | ProcessListFree(&ProcList); 342 | FreeSubBridgeServerTemplate(); 343 | 344 | SockClose(&MainSock); 345 | 346 | exit: 347 | 348 | PeerDataDestroy(&PeerDataRoot,&ISeedPeer); 349 | KeyInfoUpdate( &KeyInfoCache ); 350 | KeyInfoWriteFile(&KeyInfoCache,"tknet.info"); 351 | KeyInfoFree(&KeyInfoCache); 352 | RelayMuduleDestruction(); 353 | tkNetCommonUninit(); 354 | 355 | printf("unfree memory:%d \n",g_allocs); 356 | return 0; 357 | } 358 | -------------------------------------------------------------------------------- /nat_checkd.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | #define CHECK_NAT_TRY_AGAIN 0 15 | #define CHECK_NAT_FINE 1 16 | 17 | #define CHECK_MAIL_BEGIN 0 18 | #define CHECK_MAIL_SEE_IT 1 19 | #define CHECK_MAIL_NOT_SEE 2 20 | #define CHECK_MAIL_ERROR 3 21 | 22 | struct CheckNATProc 23 | { 24 | struct Process proc; 25 | struct KeyInfoCache *pKeyInfo; 26 | struct KeyInfo *pFailedKey,*pTmpContentKey; 27 | struct pipe *pCheckPipe; 28 | uchar STUNTryFlag; 29 | struct ProcessingList *pProcList; 30 | BOOL ifFisrtRun; 31 | }; 32 | 33 | struct FindPossibleKeyInfoByNotNumPa 34 | { 35 | int NotNum; 36 | struct KeyInfo *pPossible; 37 | }; 38 | 39 | struct CheckNATProc* 40 | CheckNATProcConsAndBegin(struct ProcessingList *,struct KeyInfoCache *); 41 | -------------------------------------------------------------------------------- /nattype.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | #include "tknet.h" 15 | uchar g_NATtype = NAT_T_UNKNOWN; 16 | struct NetAddr g_NATMapAddr; 17 | 18 | STEP( BindingRequest ) 19 | { 20 | struct STUNProc *pProc = GET_STRUCT_ADDR(pa_pProc , struct STUNProc , proc); 21 | struct StunHead stun; 22 | char AddrStr[32]; 23 | struct NetAddr AddrTemp; 24 | 25 | if( SockRead( pProc->pSock ) ) 26 | { 27 | VCK( 0 == StunGetResult(pProc->pSock->RecvBuff, 28 | pProc->pSock->RecvLen,pProc->MagicCookieTemp, 29 | &pProc->MapAddr,&pProc->ChangeAddr) ,return PS_CALLBK_RET_GO_ON; ); 30 | 31 | //print details 32 | AddrTemp = GetAddrFromSockAddr(&pProc->pSock->AddrRecvfrom); 33 | GetAddrText(&AddrTemp,AddrStr); 34 | PROMPT(Usual,"recv STUN from %s ,",AddrStr); 35 | GetAddrText(&pProc->MapAddr,AddrStr); 36 | PROMPT(Usual,"saying that my public address is %s",AddrStr); 37 | GetAddrText(&pProc->ChangeAddr,AddrStr); 38 | PROMPT(Usual," and 'change address' is %s\n",AddrStr); 39 | 40 | return PS_CALLBK_RET_DONE; 41 | } 42 | else if( pa_state == PS_STATE_OVERTIME || pa_state == PS_STATE_FIRST_TIME ) 43 | { 44 | pProc->MagicCookieTemp = StunFormulateRequest( &stun ); 45 | SockLocateTa( pProc->pSock , pProc->HostIPVal , pProc->HostPort ); 46 | SockWrite( pProc->pSock , BYS(stun) ); 47 | 48 | AddrTemp = GetAddrFromSockAddr(&pProc->pSock->AddrTa); 49 | GetAddrText(&AddrTemp,AddrStr); 50 | PROMPT(Usual,"Binding request to %s..\n",AddrStr); 51 | } 52 | else if( pa_state == PS_STATE_LAST_TIME ) 53 | { 54 | return PS_CALLBK_RET_ABORT; 55 | } 56 | 57 | return PS_CALLBK_RET_GO_ON; 58 | } 59 | 60 | STEP( ChangeIPAndPort ) 61 | { 62 | struct STUNProc *pProc = GET_STRUCT_ADDR(pa_pProc , struct STUNProc , proc); 63 | struct ChangeRequest cr_stun; 64 | char AddrStr[32]; 65 | struct NetAddr AddrTemp; 66 | 67 | if( SockRead( pProc->pSock ) ) 68 | { 69 | VCK( 0 == StunGetResult(pProc->pSock->RecvBuff, 70 | pProc->pSock->RecvLen,pProc->MagicCookieTemp, 71 | &AddrTemp,&AddrTemp) ,return PS_CALLBK_RET_GO_ON; ); 72 | //just to check whether it is a valid STUN datagram 73 | 74 | AddrTemp = GetAddrFromSockAddr(&pProc->pSock->AddrRecvfrom); 75 | 76 | VCK( AddrTemp.IPv4 == ntohl(pProc->HostIPVal) , return PS_CALLBK_RET_GO_ON; ); 77 | VCK( AddrTemp.port == pProc->HostPort , return PS_CALLBK_RET_GO_ON; ); 78 | //check if IP and port both has changed. 79 | 80 | GetAddrText(&AddrTemp,AddrStr); 81 | PROMPT(Usual,"recv STUN from %s \n",AddrStr); 82 | //print details 83 | 84 | pProc->NatTypeRes = NAT_T_FULL_CONE; 85 | //we are not sure if it is a 'cone NAT' actually , but we mark it as full-cone NAT 86 | //in advance . we make confirm in next step by testing whether it map the same port 87 | //session when sending to a different IP. 88 | 89 | return PS_CALLBK_RET_DONE; 90 | } 91 | else if( pa_state == PS_STATE_OVERTIME || pa_state == PS_STATE_FIRST_TIME ) 92 | { 93 | pProc->MagicCookieTemp = StunFormulateChangeRequest( &cr_stun , STUN_CHANGE_BOTH_IP_PORT ); 94 | SockLocateTa( pProc->pSock , pProc->HostIPVal , pProc->HostPort ); 95 | SockWrite( pProc->pSock , BYS(cr_stun) ); 96 | 97 | AddrTemp = GetAddrFromSockAddr(&pProc->pSock->AddrTa); 98 | GetAddrText(&AddrTemp,AddrStr); 99 | PROMPT(Usual,"Sending ChangeIPAndPort request to %s ..\n",AddrStr); 100 | } 101 | else if( pa_state == PS_STATE_LAST_TIME ) 102 | { 103 | return PS_CALLBK_RET_DONE; 104 | } 105 | 106 | return PS_CALLBK_RET_GO_ON; 107 | } 108 | 109 | STEP( BindingRequestToAnotherServer ) 110 | { 111 | struct STUNProc *pProc = GET_STRUCT_ADDR(pa_pProc , struct STUNProc , proc); 112 | struct StunHead stun; 113 | char AddrStr[32]; 114 | struct NetAddr AddrTemp; 115 | 116 | if( SockRead( pProc->pSock ) ) 117 | { 118 | AddrTemp = GetAddrFromSockAddr(&pProc->pSock->AddrRecvfrom); 119 | VCK( AddrTemp.IPv4 != pProc->ChangeAddr.IPv4 , return PS_CALLBK_RET_GO_ON; ); 120 | 121 | VCK( 0 == StunGetResult(pProc->pSock->RecvBuff, 122 | pProc->pSock->RecvLen,pProc->MagicCookieTemp, 123 | &AddrTemp,&pProc->ChangeAddr) ,return PS_CALLBK_RET_GO_ON; ); 124 | 125 | if( AddrTemp.port != pProc->MapAddr.port ) 126 | { 127 | pProc->NatTypeRes = NAT_T_SYMMETRIC; 128 | } 129 | 130 | pProc->MapAddr = AddrTemp; 131 | 132 | //print details 133 | AddrTemp = GetAddrFromSockAddr(&pProc->pSock->AddrRecvfrom); 134 | GetAddrText(&AddrTemp,AddrStr); 135 | PROMPT(Usual,"recv STUN from %s ,",AddrStr); 136 | GetAddrText(&pProc->MapAddr,AddrStr); 137 | PROMPT(Usual,"saying that my public address is %s\n",AddrStr); 138 | 139 | if( pProc->NatTypeRes == NAT_T_SYMMETRIC ) 140 | { 141 | return PS_CALLBK_RET_ABORT; 142 | } 143 | else if( pProc->NatTypeRes == NAT_T_FULL_CONE ) 144 | { 145 | //now we assure that it is full-cone. 146 | return PS_CALLBK_RET_ABORT; 147 | } 148 | else 149 | { 150 | return PS_CALLBK_RET_DONE; 151 | } 152 | } 153 | else if( pa_state == PS_STATE_OVERTIME || pa_state == PS_STATE_FIRST_TIME ) 154 | { 155 | pProc->MagicCookieTemp = StunFormulateRequest( &stun ); 156 | SockLocateTa( pProc->pSock , htonl(pProc->ChangeAddr.IPv4) , STUN_DEFAULT_PORT ); 157 | //use STUN_DEFAULT_PORT instead of the port returned by CHANGE_ADDRESS 158 | SockWrite( pProc->pSock , BYS(stun) ); 159 | 160 | AddrTemp = GetAddrFromSockAddr(&pProc->pSock->AddrTa); 161 | GetAddrText(&AddrTemp,AddrStr); 162 | PROMPT(Usual,"Binding request to server #2(%s)..\n",AddrStr); 163 | } 164 | else if( pa_state == PS_STATE_LAST_TIME ) 165 | { 166 | return PS_CALLBK_RET_ABORT; 167 | } 168 | 169 | return PS_CALLBK_RET_GO_ON; 170 | } 171 | 172 | STEP( ChangePort ) 173 | { 174 | struct STUNProc *pProc = GET_STRUCT_ADDR(pa_pProc , struct STUNProc , proc); 175 | struct ChangeRequest cr_stun; 176 | char AddrStr[32]; 177 | struct NetAddr AddrTemp; 178 | 179 | if( SockRead( pProc->pSock ) ) 180 | { 181 | VCK( 0 == StunGetResult(pProc->pSock->RecvBuff, 182 | pProc->pSock->RecvLen,pProc->MagicCookieTemp, 183 | &AddrTemp,&AddrTemp) ,return PS_CALLBK_RET_GO_ON; ); 184 | //just to check whether it is a valid STUN datagram 185 | 186 | AddrTemp = GetAddrFromSockAddr(&pProc->pSock->AddrRecvfrom); 187 | 188 | VCK( AddrTemp.IPv4 != ntohl(pProc->HostIPVal) , return PS_CALLBK_RET_GO_ON; ); 189 | VCK( AddrTemp.port == pProc->HostPort , return PS_CALLBK_RET_GO_ON; ); 190 | //check if port has changed while IP stays the same. 191 | 192 | GetAddrText(&AddrTemp,AddrStr); 193 | PROMPT(Usual,"recv STUN from %s \n",AddrStr); 194 | //print details 195 | 196 | pProc->NatTypeRes = NAT_T_RESTRICTED; 197 | return PS_CALLBK_RET_ABORT; 198 | } 199 | else if( pa_state == PS_STATE_OVERTIME || pa_state == PS_STATE_FIRST_TIME ) 200 | { 201 | pProc->MagicCookieTemp = StunFormulateChangeRequest( &cr_stun , STUN_CHANGE_PORT ); 202 | SockLocateTa( pProc->pSock , pProc->HostIPVal , pProc->HostPort ); 203 | SockWrite( pProc->pSock , BYS(cr_stun) ); 204 | 205 | AddrTemp = GetAddrFromSockAddr(&pProc->pSock->AddrTa); 206 | GetAddrText(&AddrTemp,AddrStr); 207 | PROMPT(Usual,"Sending ChangePort request to %s ..\n",AddrStr); 208 | } 209 | else if( pa_state == PS_STATE_LAST_TIME ) 210 | { 211 | pProc->NatTypeRes = NAT_T_PORT_RESTRICTED; 212 | return PS_CALLBK_RET_ABORT; 213 | } 214 | 215 | return PS_CALLBK_RET_GO_ON; 216 | } 217 | 218 | void 219 | MakeProtoStunProc( struct STUNProc *pa_pStunProc ,struct Sock *pa_pSock , const char *pa_pHostIP , ushort pa_HostPort ) 220 | { 221 | ProcessCons( &pa_pStunProc->proc ); 222 | PROCESS_ADD_STEP( &pa_pStunProc->proc , BindingRequest , g_WaitLevel[2] ); 223 | PROCESS_ADD_STEP( &pa_pStunProc->proc , ChangeIPAndPort , g_WaitLevel[2] ); 224 | //put ChangeIPAndPort to test whether it's under a Full-cone NAT *Before* BindingRequestToAnotherServer 225 | //because BindingRequestToAnotherServer will punch a hole which will lead a false judgement later. 226 | PROCESS_ADD_STEP( &pa_pStunProc->proc , BindingRequestToAnotherServer , g_WaitLevel[2]); 227 | PROCESS_ADD_STEP( &pa_pStunProc->proc , ChangePort , g_WaitLevel[2] ); 228 | //we can assert that we were under a Port-restricted cone NAT if nothing recved from ChangePort step 229 | //without further test, because Port-restricted cone NAT actually is the most stricted NAT of all types of 230 | //cone NATs and we have already confirmed our NAT is a kind of cone NAT in the BindingRequestToAnotherServer 231 | //step. 232 | 233 | pa_pStunProc->HostIPVal = GetIPVal( pa_pHostIP ); 234 | pa_pStunProc->HostPort = pa_HostPort; 235 | pa_pStunProc->pSock = pa_pSock; 236 | pa_pStunProc->NatTypeRes = NAT_T_UNKNOWN; 237 | } 238 | 239 | void 240 | NatTypePrint(uchar pa_type) 241 | { 242 | PROMPT(Usual,"NAT type: %d ",pa_type); 243 | 244 | switch( pa_type ) 245 | { 246 | case NAT_T_FULL_CONE: 247 | PROMPT(Usual,"(full cone)\n"); 248 | break; 249 | case NAT_T_RESTRICTED: 250 | PROMPT(Usual,"(restricted cone)\n"); 251 | break; 252 | case NAT_T_PORT_RESTRICTED: 253 | PROMPT(Usual,"(port restricted cone)\n"); 254 | break; 255 | case NAT_T_SYMMETRIC: 256 | PROMPT(Usual,"(symmetric)\n"); 257 | break; 258 | default: 259 | PROMPT(Usual,"(unknown)\n"); 260 | } 261 | } 262 | -------------------------------------------------------------------------------- /nattype.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | #define NAT_T_FULL_CONE 0x00 15 | #define NAT_T_RESTRICTED 0x01 16 | #define NAT_T_PORT_RESTRICTED 0x02 17 | #define NAT_T_SYMMETRIC 0x03 18 | #define NAT_T_UNKNOWN 0x04 19 | 20 | struct STUNProc 21 | { 22 | struct Process proc; 23 | struct Sock *pSock; 24 | int HostIPVal; 25 | ushort HostPort; 26 | uint MagicCookieTemp; 27 | struct NetAddr MapAddr; 28 | struct NetAddr ChangeAddr; 29 | uchar NatTypeRes; 30 | }; 31 | 32 | void 33 | MakeProtoStunProc( struct STUNProc * ,struct Sock * , const char * , ushort ); 34 | 35 | void 36 | NatTypePrint(uchar); 37 | 38 | extern uchar g_NATtype; 39 | extern struct NetAddr g_NATMapAddr; 40 | //g_NATMapAddr is recorded not for sending to BDG server 41 | //for register(the map addr is obtained through recved socket 42 | //by BDG server), however, it is used for bkgd process, specifically 43 | //the check NAT process to compare, and know whether map addr has 44 | //changed. 45 | -------------------------------------------------------------------------------- /netaddr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | struct NetAddr 15 | { 16 | uint IPv4; 17 | // = ntohl( GetIPVal(IP text) ) 18 | // IP text = GetAddrText(GetAddrFromSockAddr(sock_addr)) 19 | ushort port; 20 | }; 21 | 22 | static __inline struct NetAddr 23 | NetAddr(const char *pa_pIPText,ushort pa_port) 24 | { 25 | struct NetAddr res; 26 | res.IPv4 = ntohl(GetIPVal(pa_pIPText)); 27 | res.port = pa_port; 28 | 29 | return res; 30 | } 31 | 32 | static __inline void 33 | GetIPText( struct NetAddr *pa_pAddr , char *out_str) 34 | { 35 | struct sockaddr_in SockAddr; 36 | char *pResBuff; 37 | SockAddr.sin_addr.s_addr = htonl(pa_pAddr->IPv4); 38 | pResBuff = (char*)inet_ntoa(SockAddr.sin_addr); 39 | strcpy( out_str , pResBuff ); 40 | } 41 | 42 | static __inline void 43 | GetAddrText( struct NetAddr *pa_pAddr , char *out_str) 44 | { 45 | char buff[32]; 46 | GetIPText(pa_pAddr,out_str); 47 | sprintf(buff,"/%d",pa_pAddr->port); 48 | strcat(out_str,buff); 49 | } 50 | 51 | static __inline struct NetAddr 52 | GetAddrFromSockAddr( struct sockaddr_in *in_SockAddr) 53 | { 54 | struct NetAddr res; 55 | res.port = ntohs(in_SockAddr->sin_port); 56 | res.IPv4 = ntohl(in_SockAddr->sin_addr.s_addr); 57 | 58 | return res; 59 | } 60 | 61 | static __inline BOOL 62 | ifNetAddrEqual(struct NetAddr *pa_0,struct NetAddr *pa_1) 63 | { 64 | return ( pa_0->IPv4 == pa_1->IPv4 && pa_0->port == pa_1->port ); 65 | } 66 | -------------------------------------------------------------------------------- /netproc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | #include "tknet.h" 15 | 16 | DEF_STRUCT_CONSTRUCTOR( Process , 17 | out_cons->IProcessHead = GetIterator(NULL); 18 | out_cons->IProcessNow = GetIterator(NULL); 19 | ListNodeCons(&out_cons->UndergoLN); 20 | out_cons->CurrentStepStartTime = 0; 21 | out_cons->CurrentStepRetrys = 0; 22 | out_cons->NotifyCallbk = NULL; 23 | out_cons->steps = 0; 24 | ) 25 | 26 | DEF_STRUCT_CONSTRUCTOR( ProcessingList , 27 | out_cons->IUndergoProcess = GetIterator(NULL); 28 | ) 29 | 30 | 31 | struct WatiLevel g_WaitLevel[TKNET_WAIT_LEVELS]; 32 | 33 | 34 | long sta_WaitValue[TKNET_CONDITIONS][TKNET_WAIT_LEVELS] = { 35 | {600,1000,1500,9000,20000,60000}, //under good net condition (condition0) 36 | {600,1500,2000,9000,20000,1800000}, //under nomal net condition (condition1) 37 | {600,2000,2000,9000,20000,6400000}}; //under bad net condition (condition2) 38 | //level: 0 1 2 3 4 5 39 | 40 | //NOTE: we currently use level 0 for result muti-sending, its wait value doesn't change. 41 | //we currently use level 3 and 4 for client "wait step" and main server loop step, 42 | //its wait value doesn't change either; level 5 for NAT Check interval. 43 | 44 | uchar sta_RetryValue[TKNET_CONDITIONS][TKNET_WAIT_LEVELS] = { 45 | { 2, 1, 1, 1, 1 , 1}, 46 | { 2, 2, 2, 2, 2 , 1}, 47 | { 3, 3, 3, 3, 3 , 1}}; 48 | 49 | static void 50 | ProcessTraceCondition(uint pa_condition) 51 | { 52 | int i; 53 | long **ppl; 54 | uchar **ppc; 55 | 56 | VCK( pa_condition >= TKNET_CONDITIONS ,return); 57 | PROMPT(Usual,"tknet condition: %d \n",pa_condition); 58 | 59 | for(i=0 ; i < TKNET_WAIT_LEVELS ; i++ ) 60 | { 61 | ppl=&g_WaitLevel[i].pInterval; 62 | ppc=&g_WaitLevel[i].pRetrys; 63 | PROMPT(Usual,"level%d: %ld*%d \n",i,**ppl,**ppc); 64 | } 65 | } 66 | 67 | void 68 | ProcessSetCondition(uint pa_condition) 69 | { 70 | int i; 71 | VCK( pa_condition >= TKNET_CONDITIONS , 72 | PROMPT(Usual,"Setting condition failed, invalid num.\n");return); 73 | 74 | for(i=0 ; i < TKNET_WAIT_LEVELS ; i++ ) 75 | { 76 | g_WaitLevel[i].pInterval = &sta_WaitValue[pa_condition][i]; 77 | g_WaitLevel[i].pRetrys = &sta_RetryValue[pa_condition][i]; 78 | } 79 | 80 | PROMPT(Usual,"Set ");ProcessTraceCondition(pa_condition); 81 | } 82 | 83 | static void 84 | ProcessUpdateCurrentStep(struct Process *pa_pProc) 85 | { 86 | struct ProcessStep *pStep = GET_STRUCT_ADDR_FROM_IT( &pa_pProc->IProcessNow , struct ProcessStep , ProcStepLN ); 87 | pa_pProc->CurrentStepStartTime = tkMilliseconds(); 88 | pa_pProc->CurrentStepRetrys = **pStep->ppMaxRetrys; 89 | pa_pProc->isCurrentStepFirstTime = 1; 90 | } 91 | 92 | void 93 | ProcessAddStep( struct Process *pa_pProc , StepCallbk pa_StepDo , long **pa_ppWaitClocks , uchar **pa_ppMaxRetrys , const char *pa_pName ) 94 | { 95 | struct ProcessStep *pNewStep = tkmalloc( struct ProcessStep ); 96 | 97 | pNewStep->FlagNum = pa_pProc->steps; 98 | pNewStep->ppWaitClocks = pa_ppWaitClocks; 99 | pNewStep->ppMaxRetrys = pa_ppMaxRetrys; 100 | pNewStep->StepDo = pa_StepDo; 101 | ListNodeCons(&pNewStep->ProcStepLN); 102 | pNewStep->pName = pa_pName; 103 | 104 | AddOneToListTail( &pa_pProc->IProcessHead , &pNewStep->ProcStepLN ); 105 | pa_pProc->steps ++; 106 | } 107 | 108 | void 109 | ProcessConsAndSetSteps( struct Process *out_proc , struct Process *in_proc ) 110 | { 111 | ProcessCons( out_proc ); 112 | out_proc->IProcessHead = in_proc->IProcessHead; 113 | out_proc->steps = in_proc->steps; 114 | } 115 | 116 | void 117 | ProcessStart( struct Process *pa_pProc , struct ProcessingList *pa_pProcList ) 118 | { 119 | pa_pProc->IProcessNow = pa_pProc->IProcessHead; 120 | ProcessUpdateCurrentStep( pa_pProc ); 121 | AddOneToListTail( &pa_pProcList->IUndergoProcess , &pa_pProc->UndergoLN ); 122 | } 123 | 124 | void 125 | ProcessSafeStart( struct Process *pa_pProc , struct ProcessingList *pa_pProcList , struct Iterator *pa_pINow , struct Iterator *pa_pIForward ) 126 | { 127 | pa_pProc->IProcessNow = pa_pProc->IProcessHead; 128 | ProcessUpdateCurrentStep( pa_pProc ); 129 | AddOneToListTailSafe( &pa_pProcList->IUndergoProcess , pa_pINow , pa_pIForward , &pa_pProc->UndergoLN ); 130 | } 131 | 132 | static BOOL 133 | LIST_ITERATION_CALLBACK_FUNCTION( FindStepWithFlagNum ) 134 | { 135 | struct ProcessStep *pStep = GET_STRUCT_ADDR_FROM_IT( pa_pINow , struct ProcessStep , ProcStepLN ); 136 | DEF_AND_CAST( pFswfnp , struct FindStepWithFlagNumPa , pa_else ); 137 | 138 | if( pStep->FlagNum == pFswfnp->FlagNumToFind ) 139 | { 140 | pFswfnp->IFound = *pa_pINow; 141 | return 1; 142 | } 143 | else 144 | { 145 | return pa_pINow->now == pa_pIHead->last; 146 | } 147 | } 148 | 149 | static BOOL 150 | LIST_ITERATION_CALLBACK_FUNCTION( DoProcess ) 151 | { 152 | uchar ps_res,ps_state = PS_STATE_NORMAL; 153 | long dt; 154 | struct Process *pProc = GET_STRUCT_ADDR_FROM_IT( pa_pINow , struct Process , UndergoLN ); 155 | struct ProcessStep *pStep = GET_STRUCT_ADDR_FROM_IT( &pProc->IProcessNow , struct ProcessStep , ProcStepLN ); 156 | struct FindStepWithFlagNumPa fswfpa; 157 | DEF_AND_CAST(pProcList,struct ProcessingList,pa_else); 158 | 159 | if( pProc->isCurrentStepFirstTime ) 160 | { 161 | pProc->isCurrentStepFirstTime = 0; 162 | ps_state = PS_STATE_FIRST_TIME; 163 | } 164 | else if( tkMilliseconds() < pProc->CurrentStepStartTime ) 165 | { 166 | pProc->CurrentStepStartTime = tkMilliseconds(); 167 | } 168 | else 169 | { 170 | dt = tkMilliseconds() - pProc->CurrentStepStartTime; 171 | if( dt > **pStep->ppWaitClocks ) 172 | { 173 | if( pProc->CurrentStepRetrys == 0 ) 174 | { 175 | ps_state = PS_STATE_LAST_TIME; 176 | } 177 | else 178 | { 179 | pProc->CurrentStepRetrys --; 180 | pProc->CurrentStepStartTime = tkMilliseconds(); 181 | ps_state = PS_STATE_OVERTIME; 182 | } 183 | } 184 | } 185 | 186 | ps_res = pStep->StepDo( pProc , ps_state , pa_pINow , pa_pIForward ); 187 | 188 | if( (ps_res & 0x80) == 0x00 ) 189 | { 190 | fswfpa.FlagNumToFind = ps_res; 191 | fswfpa.IFound = GetIterator(NULL); 192 | ForEach( &pProc->IProcessHead , &FindStepWithFlagNum , &fswfpa ); 193 | 194 | if(fswfpa.IFound.now == NULL) 195 | { 196 | ps_res = PS_CALLBK_RET_DONE; 197 | } 198 | else 199 | { 200 | pProc->IProcessNow = fswfpa.IFound; 201 | ProcessUpdateCurrentStep( pProc ); 202 | goto ret; 203 | } 204 | } 205 | 206 | switch( ps_res ) 207 | { 208 | case PS_CALLBK_RET_ABORT: 209 | 210 | if( pProc->NotifyCallbk != NULL ) 211 | pProc->NotifyCallbk( pProc ); 212 | 213 | return ProcessDisattach(pProc,pProcList); 214 | 215 | case PS_CALLBK_RET_GO_ON: 216 | 217 | if( ps_state != PS_STATE_LAST_TIME ) 218 | { 219 | break; 220 | } 221 | 222 | case PS_CALLBK_RET_DONE: 223 | 224 | if( pProc->IProcessNow.now == pProc->IProcessHead.last ) 225 | { 226 | if( pProc->NotifyCallbk != NULL ) 227 | pProc->NotifyCallbk( pProc ); 228 | 229 | return ProcessDisattach(pProc,pProcList); 230 | } 231 | else 232 | { 233 | pProc->IProcessNow = GetIterator( pProc->IProcessNow.now->next ); 234 | } 235 | 236 | case PS_CALLBK_RET_REDO: 237 | 238 | ProcessUpdateCurrentStep( pProc ); 239 | break; 240 | 241 | default: 242 | TK_EXCEPTION( "proc step callbk return" ); 243 | break; 244 | 245 | } 246 | 247 | ret: 248 | return pa_pINow->now == pa_pIHead->last; 249 | } 250 | 251 | void 252 | DoProcessing( struct ProcessingList *pa_pProcList ) 253 | { 254 | ForEach( &pa_pProcList->IUndergoProcess , &DoProcess , pa_pProcList ); 255 | } 256 | 257 | DEF_FREE_LIST_ELEMENT_CALLBACK_FUNCTION( FreeProcStep , struct ProcessStep , ProcStepLN , ; ) 258 | 259 | void 260 | ProcessFree( struct Process *pa_pProc ) 261 | { 262 | ForEach(&pa_pProc->IProcessHead,&FreeProcStep,NULL); 263 | } 264 | 265 | BOOL 266 | ProcessDisattach( struct Process* pa_pProc , struct ProcessingList *pa_pProcList ) 267 | { 268 | if(pa_pProc->UndergoLN.next == &pa_pProc->UndergoLN 269 | && pa_pProcList->IUndergoProcess.now != &pa_pProc->UndergoLN) 270 | return 0;//not attached, do nothing. 271 | else 272 | return ListDragOneOut(&pa_pProcList->IUndergoProcess,&pa_pProc->UndergoLN); 273 | } 274 | 275 | static BOOL 276 | LIST_ITERATION_CALLBACK_FUNCTION( TraceProcStep ) 277 | { 278 | struct ProcessStep *pProcStep = GET_STRUCT_ADDR_FROM_IT( pa_pINow , struct ProcessStep , ProcStepLN ); 279 | char PrintStr[128]; 280 | char BuffStr[128]; 281 | DEF_AND_CAST( pProc , struct Process , pa_else ); 282 | 283 | if( pa_pINow->now == pProc->IProcessNow.now ) 284 | { 285 | strcpy(PrintStr , "Now("); 286 | } 287 | else 288 | { 289 | strcpy(PrintStr , "("); 290 | } 291 | 292 | sprintf( BuffStr , "STEP%d" , pProcStep->FlagNum ); 293 | strcat( PrintStr , BuffStr ); 294 | strcat( PrintStr , ","); 295 | 296 | if( pProcStep->pName != NULL ) 297 | { 298 | sprintf( BuffStr , "%s" , pProcStep->pName ); 299 | strcat( PrintStr , BuffStr ); 300 | strcat( PrintStr , ","); 301 | } 302 | 303 | sprintf( BuffStr , "%ld" , **pProcStep->ppWaitClocks ); 304 | strcat( PrintStr , BuffStr ); 305 | strcat( PrintStr , "*"); 306 | 307 | sprintf( BuffStr , "%d" , **pProcStep->ppMaxRetrys ); 308 | strcat( PrintStr , BuffStr ); 309 | strcat( PrintStr , ")"); 310 | 311 | if( pa_pINow->now == pa_pIHead->last ) 312 | { 313 | PROMPT(Usual,"%s \n" ,PrintStr); 314 | return 1; 315 | } 316 | else 317 | { 318 | PROMPT(Usual,"%s->" ,PrintStr); 319 | return 0; 320 | } 321 | } 322 | 323 | void 324 | ProcessTraceSteps(struct Process *pa_pProc) 325 | { 326 | ForEach( &pa_pProc->IProcessHead , &TraceProcStep , pa_pProc ); 327 | } 328 | 329 | static BOOL 330 | LIST_ITERATION_CALLBACK_FUNCTION( FindStepByName ) 331 | { 332 | struct ProcessStep *pProcStep = GET_STRUCT_ADDR_FROM_IT( pa_pINow , struct ProcessStep , ProcStepLN ); 333 | DEF_AND_CAST(pFsbnpa,struct FindStepByNamePa,pa_else); 334 | 335 | if( strcmp(pFsbnpa->pNameToFind , pProcStep->pName) == 0 ) 336 | { 337 | pFsbnpa->pFound = pProcStep; 338 | return 1; 339 | } 340 | else 341 | { 342 | return pa_pINow->now == pa_pIHead->last; 343 | } 344 | } 345 | 346 | uchar 347 | FlagName(struct Process *pa_pProc ,const char *pa_pName) 348 | { 349 | struct FindStepByNamePa fsbnpa; 350 | fsbnpa.pFound = NULL; 351 | fsbnpa.pNameToFind = pa_pName; 352 | 353 | ForEach( &pa_pProc->IProcessHead , &FindStepByName , &fsbnpa ); 354 | 355 | if(fsbnpa.pFound) 356 | { 357 | return fsbnpa.pFound->FlagNum; 358 | } 359 | else 360 | { 361 | return PS_CALLBK_RET_DONE; 362 | } 363 | } 364 | 365 | static BOOL 366 | LIST_ITERATION_CALLBACK_FUNCTION( ProcessingListTraceCallbk ) 367 | { 368 | DEF_AND_CAST(pCount,int,pa_else); 369 | (*pCount) ++; 370 | 371 | return pa_pINow->now == pa_pIHead->last; 372 | } 373 | 374 | void 375 | ProcessingListTrace(struct ProcessingList *pa_pProcList) 376 | { 377 | //only implemented the counting function now. 378 | int count = 0; 379 | ForEach( &pa_pProcList->IUndergoProcess , &ProcessingListTraceCallbk , &count ); 380 | PROMPT(Usual,"Processing %d processes. \n",count); 381 | } 382 | 383 | static BOOL 384 | LIST_ITERATION_CALLBACK_FUNCTION( FreeProcess ) 385 | { 386 | struct Process *pProc = GET_STRUCT_ADDR_FROM_IT( pa_pINow , struct Process , UndergoLN ); 387 | 388 | tk( pa_pINow , pa_pIForward ); 389 | 390 | if( pProc->NotifyCallbk != NULL ) 391 | pProc->NotifyCallbk( pProc ); 392 | 393 | if( pa_pINow->now == pa_pIHead->last ) 394 | { 395 | *pa_pIHead = GetIterator( NULL ); 396 | return 1; 397 | }else 398 | { 399 | return 0; 400 | } 401 | } 402 | 403 | void 404 | ProcessListFree(struct ProcessingList * pa_pProcList) 405 | { 406 | ForEach( &pa_pProcList->IUndergoProcess , &FreeProcess , NULL ); 407 | } 408 | -------------------------------------------------------------------------------- /netproc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | #define PS_STATE_FIRST_TIME 0x00 15 | #define PS_STATE_NORMAL 0x01 16 | #define PS_STATE_OVERTIME 0x02 17 | #define PS_STATE_LAST_TIME 0x03 18 | 19 | #define PS_CALLBK_RET_ABORT (0x00|0x80) 20 | #define PS_CALLBK_RET_GO_ON (0x01|0x80) 21 | #define PS_CALLBK_RET_DONE (0x02|0x80) 22 | #define PS_CALLBK_RET_REDO (0x03|0x80) 23 | #define PS_CALLBK_RET_TO_END (0x04|0x80) 24 | 25 | struct ProcessingList 26 | { 27 | struct Iterator IUndergoProcess; 28 | }; 29 | 30 | struct Process 31 | { 32 | struct Iterator IProcessHead; 33 | struct Iterator IProcessNow; 34 | struct ListNode UndergoLN; 35 | long CurrentStepStartTime; 36 | uchar CurrentStepRetrys; 37 | BOOL isCurrentStepFirstTime; 38 | uchar steps; 39 | 40 | void (*NotifyCallbk)( struct Process * ); 41 | }; 42 | 43 | typedef uchar (*StepCallbk)( struct Process* , uchar, struct Iterator*, struct Iterator*); 44 | 45 | #define STEP( _step_name ) \ 46 | const char ProcessStepName ## _step_name [] = # _step_name ; \ 47 | uchar ProcessStep ## _step_name (struct Process* pa_pProc , uchar pa_state , struct Iterator* pa_pINow, struct Iterator* pa_pIForward ) 48 | 49 | #define EXTERN_STEP( _step_name ) \ 50 | extern const char ProcessStepName ## _step_name []; \ 51 | uchar ProcessStep ## _step_name (struct Process* , uchar , struct Iterator*, struct Iterator*); 52 | 53 | #define PROCESS_ADD_STEP( _pProc , _step , _WaitLevel ) \ 54 | ProcessAddStep( _pProc , & ( ProcessStep ## _step ) , &( _WaitLevel .pInterval) , &( _WaitLevel .pRetrys) , ProcessStepName ## _step ) 55 | 56 | #define TKNET_WAIT_LEVELS 6 57 | #define TKNET_CONDITIONS 3 58 | 59 | struct WatiLevel 60 | { 61 | long *pInterval; 62 | uchar *pRetrys; 63 | }; 64 | 65 | struct ProcessStep 66 | { 67 | uchar FlagNum; 68 | long **ppWaitClocks; 69 | uchar **ppMaxRetrys; 70 | StepCallbk StepDo; 71 | struct ListNode ProcStepLN; 72 | const char *pName; 73 | }; 74 | 75 | struct FindStepWithFlagNumPa 76 | { 77 | uchar FlagNumToFind; 78 | struct Iterator IFound; 79 | }; 80 | 81 | struct FindStepByNamePa 82 | { 83 | const char *pNameToFind; 84 | struct ProcessStep *pFound; 85 | }; 86 | 87 | DECLARATION_STRUCT_CONSTRUCTOR( Process ) 88 | DECLARATION_STRUCT_CONSTRUCTOR( ProcessingList ) 89 | 90 | static __inline uchar 91 | FlagNum(uchar pa_FlagNum) 92 | { 93 | return pa_FlagNum; 94 | } 95 | 96 | uchar 97 | FlagName(struct Process * ,const char *); 98 | 99 | void 100 | ProcessAddStep( struct Process* , StepCallbk , long** , uchar** , const char* ); 101 | 102 | void 103 | ProcessConsAndSetSteps( struct Process* , struct Process* ); 104 | 105 | void 106 | ProcessStart( struct Process * , struct ProcessingList* ); 107 | 108 | void 109 | ProcessSafeStart( struct Process *, struct ProcessingList *, struct Iterator *, struct Iterator *); 110 | 111 | void 112 | DoProcessing( struct ProcessingList* ); 113 | 114 | void 115 | ProcessFree( struct Process* ); 116 | 117 | void 118 | ProcessTraceSteps( struct Process* ); 119 | 120 | BOOL 121 | ProcessDisattach( struct Process* pa_pProc , struct ProcessingList *pa_pProcList ); 122 | //Call this function to stop this process from 123 | //executing. When disattached. 124 | //the process will start from begining next time 125 | //it is started by ProcessStart(). 126 | 127 | void 128 | ProcessingListTrace(struct ProcessingList *); 129 | 130 | extern struct WatiLevel g_WaitLevel[TKNET_WAIT_LEVELS]; 131 | 132 | void 133 | ProcessSetCondition( uint ); 134 | 135 | void 136 | ProcessListFree(struct ProcessingList *); 137 | -------------------------------------------------------------------------------- /peerdata.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | #include "tknet.h" 15 | 16 | DEF_STRUCT_CONSTRUCTOR( PeerData , 17 | out_cons->addr.port = 0; 18 | out_cons->addr.IPv4 = 0; 19 | BridgeProcCons(&out_cons->BdgProc); 20 | TreapCons(&out_cons->tpnd); 21 | out_cons->TreeLevel = 0; 22 | strcpy(out_cons->NameID,"unnamed"); 23 | out_cons->NATType = NAT_T_UNKNOWN; 24 | out_cons->pSeedPeer = NULL; 25 | ) 26 | 27 | static BOOL 28 | ifPeerDataTreapNodeEqual(struct BinTreeNode* pa_pBinNode0 , 29 | struct BinTreeNode* pa_pBinNode1 , void* pa_else) 30 | { 31 | struct PeerData* p0 = GET_STRUCT_ADDR( pa_pBinNode0 , struct PeerData , tpnd.btnd ); 32 | struct PeerData* p1 = GET_STRUCT_ADDR( pa_pBinNode1 , struct PeerData , tpnd.btnd ); 33 | 34 | return ( 0 == strcmp(p0->NameID,p1->NameID) ); 35 | } 36 | 37 | static BOOL 38 | PeerDataTreapNodeCompare(struct BinTreeNode* pa_pBinNode0 , 39 | struct BinTreeNode* pa_pBinNode1 , void* pa_else) 40 | { 41 | struct PeerData* p0 = GET_STRUCT_ADDR( pa_pBinNode0 , struct PeerData , tpnd.btnd ); 42 | struct PeerData* p1 = GET_STRUCT_ADDR( pa_pBinNode1 , struct PeerData , tpnd.btnd ); 43 | uint i; 44 | for( i = 0; i < PEER_NAME_ID_LEN ; i++) 45 | { 46 | if(p0->NameID[i] == p1->NameID[i]) 47 | { 48 | continue; 49 | } 50 | else 51 | { 52 | return p0->NameID[i] > p1->NameID[i]; 53 | } 54 | } 55 | 56 | return 0; 57 | } 58 | 59 | void 60 | PeerDataInsert(struct PeerData *pa_pPD,struct PeerData *pa_pRoot) 61 | { 62 | TreapInsert(&pa_pPD->tpnd,&pa_pRoot->tpnd,&PeerDataTreapNodeCompare,NULL); 63 | } 64 | 65 | struct PeerData* 66 | PeerDataFind(struct PeerData *pa_pRoot,char *pa_pNameToFind) 67 | { 68 | struct PeerData ToFind; 69 | struct BinTreeNode *pFound; 70 | strcpy(ToFind.NameID,pa_pNameToFind); 71 | 72 | pFound = BinTreeFind(&(pa_pRoot->tpnd.btnd),&ToFind.tpnd.btnd, 73 | &PeerDataTreapNodeCompare,&ifPeerDataTreapNodeEqual,NULL); 74 | 75 | if(pFound) 76 | { 77 | return GET_STRUCT_ADDR( pFound , struct PeerData , tpnd.btnd ); 78 | } 79 | else 80 | { 81 | return NULL; 82 | } 83 | } 84 | 85 | static BOOL 86 | LIST_ITERATION_CALLBACK_FUNCTION( TracePeerData ) 87 | { 88 | struct Branch* pBranch = 89 | GET_STRUCT_ADDR_FROM_IT( pa_pINow , struct Branch , ln); 90 | 91 | struct PeerData* pData = 92 | GET_STRUCT_ADDR( pBranch->pChild , struct PeerData , tpnd.btnd.tnd); 93 | 94 | uint i; 95 | char PosFlagChar; 96 | struct BinTreeNode *pBinFather; 97 | char AddrBuff[32]; 98 | char SeedStr[32]; 99 | 100 | for( i = 0 ; i < pData->TreeLevel ; i++ ) 101 | { 102 | PROMPT(Usual,"--"); 103 | } 104 | 105 | pBinFather = GET_STRUCT_ADDR(pData->tpnd.btnd.tnd.pFather, struct BinTreeNode , tnd); 106 | 107 | if(pBinFather->RightChild == &(pData->tpnd.btnd)) 108 | { 109 | PosFlagChar = 'R'; 110 | } 111 | else if(pBinFather->LeftChild == &(pData->tpnd.btnd)) 112 | { 113 | PosFlagChar = 'L'; 114 | } 115 | else 116 | { 117 | PosFlagChar = '?'; 118 | } 119 | 120 | if(pData->pSeedPeer != NULL) 121 | { 122 | sprintf(SeedStr,"(Seed,%d)",(uint)pData->pSeedPeer->Relays); 123 | } 124 | else 125 | { 126 | SeedStr[0] = '\0'; 127 | } 128 | 129 | GetAddrText(&pData->addr,AddrBuff); 130 | 131 | PROMPT(Usual,"%s(%s) %c,Level%d,NAT%d%s,RAN%d.\n",pData->NameID,AddrBuff,PosFlagChar, 132 | pData->TreeLevel,pData->NATType,SeedStr,pData->tpnd.RanPriority); 133 | 134 | return pa_pINow->now == pa_pIHead->last; 135 | } 136 | 137 | static void 138 | PeerDataSetTreeLevel(struct TreeNode* pa_pTnd , uint pa_level) 139 | { 140 | struct PeerData *pData = 141 | GET_STRUCT_ADDR( pa_pTnd , struct PeerData , tpnd.btnd.tnd ); 142 | 143 | pData->TreeLevel = pa_level; 144 | } 145 | 146 | void 147 | PeerDataTrace(struct PeerData *pa_pRoot) 148 | { 149 | TreeGetNodesLevel(&(pa_pRoot->tpnd.btnd.tnd),&PeerDataSetTreeLevel); 150 | Traversal(&(pa_pRoot->tpnd.btnd.tnd),&PreorderDFS,&TracePeerData,NULL); 151 | } 152 | 153 | void 154 | PeerDataSelectAsSeed(struct PeerData* pa_pPD , struct Iterator *pa_pISeedList) 155 | { 156 | struct SeedPeer *pSP = tkmalloc(struct SeedPeer); 157 | 158 | ListNodeCons(&pSP->ln); 159 | pSP->pPD = pa_pPD; 160 | pSP->Relays = 0; 161 | 162 | AddOneToListTail(pa_pISeedList,&pSP->ln); 163 | 164 | pa_pPD->pSeedPeer = pSP; 165 | } 166 | 167 | static 168 | DEF_FREE_TREE_ELEMENT_CALLBACK_FUNCTION( FreePeerData , struct PeerData , tpnd.btnd.tnd ,;) 169 | 170 | static 171 | DEF_FREE_LIST_ELEMENT_SAFE_FUNCTION(FreeSeedPeer,struct SeedPeer,ln,;) 172 | 173 | void 174 | PeerDataDele(struct PeerData *pa_pPD, struct Iterator *pa_pISeedList) 175 | { 176 | struct Iterator *pIHead,IForward,INow; 177 | TreapDragOut(&pa_pPD->tpnd); 178 | 179 | if( pa_pPD->pSeedPeer == NULL ) 180 | { 181 | goto free_PD; 182 | } 183 | 184 | pIHead = pa_pISeedList; 185 | INow = GetIterator(&pa_pPD->pSeedPeer->ln); 186 | IForward = GetIterator(INow.now->next); 187 | 188 | FreeSeedPeer(pIHead,&INow,&IForward,NULL); 189 | 190 | free_PD: 191 | 192 | tkfree(pa_pPD); 193 | } 194 | 195 | void 196 | PeerDataDestroy(struct PeerData *pa_pRoot,struct Iterator *pa_pISeedList) 197 | { 198 | Traversal(&(pa_pRoot->tpnd.btnd.tnd),&PostorderDFS,&FreePeerData,NULL); 199 | 200 | ForEach(pa_pISeedList,&FreeSeedPeer,NULL); 201 | //some sub server processes is not end when the program went to exit, 202 | //and the Traversal function will NOT free the Seed of each peer 203 | //data item, so go through the Seed list and free them all. 204 | } 205 | 206 | void 207 | PeerDataUpdateSeedInfo(struct PeerData *pa_pPD,uchar pa_relays) 208 | { 209 | if( pa_pPD->pSeedPeer == NULL ) 210 | { 211 | return; 212 | } 213 | 214 | pa_pPD->pSeedPeer->Relays = pa_relays; 215 | } 216 | 217 | struct FindSeedPeerOfLeastRelaysPa 218 | { 219 | struct SeedPeer *pFound; 220 | uchar LeastRelays; 221 | }; 222 | 223 | BOOL 224 | LIST_ITERATION_CALLBACK_FUNCTION(FindSeedPeerOfLeastRelays) 225 | { 226 | struct SeedPeer *pSP = GET_STRUCT_ADDR_FROM_IT(pa_pINow,struct SeedPeer,ln); 227 | DEF_AND_CAST(pFSPOLRPa ,struct FindSeedPeerOfLeastRelaysPa ,pa_else); 228 | 229 | if( pSP->Relays <= pFSPOLRPa->LeastRelays ) 230 | { 231 | pFSPOLRPa->pFound = pSP; 232 | return 1; 233 | } 234 | else 235 | { 236 | return pa_pINow->now == pa_pIHead->last; 237 | } 238 | } 239 | 240 | struct PeerData * 241 | SeedPeerSelectOne(struct Iterator *pa_pISeedList) 242 | { 243 | struct FindSeedPeerOfLeastRelaysPa FSPOLRPa; 244 | FSPOLRPa.LeastRelays = 0; 245 | 246 | while(1) 247 | { 248 | FSPOLRPa.pFound = NULL; 249 | 250 | ForEach(pa_pISeedList,&FindSeedPeerOfLeastRelays,&FSPOLRPa); 251 | 252 | if(FSPOLRPa.pFound) 253 | { 254 | return FSPOLRPa.pFound->pPD; 255 | } 256 | 257 | FSPOLRPa.LeastRelays ++; 258 | 259 | if(FSPOLRPa.LeastRelays >= MAX_RELAYS_TO_SELECT_SEED) 260 | { 261 | break; 262 | } 263 | } 264 | 265 | return NULL; 266 | } 267 | -------------------------------------------------------------------------------- /peerdata.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | #define MAX_RELAYS_TO_SELECT_SEED 2 15 | 16 | struct SeedPeer; 17 | 18 | struct PeerData 19 | { 20 | struct NetAddr addr; 21 | struct BridgeProc BdgProc; 22 | struct Treap tpnd; 23 | uint TreeLevel; 24 | char NameID[PEER_NAME_ID_LEN]; 25 | uchar NATType; 26 | struct SeedPeer *pSeedPeer; 27 | }; 28 | 29 | struct SeedPeer 30 | { 31 | struct ListNode ln; 32 | struct PeerData *pPD; 33 | uchar Relays; 34 | }; 35 | 36 | DECLARATION_STRUCT_CONSTRUCTOR( PeerData ) 37 | 38 | void 39 | PeerDataInsert(struct PeerData *,struct PeerData *); 40 | 41 | struct PeerData* 42 | PeerDataFind(struct PeerData *,char *); 43 | 44 | void 45 | PeerDataTrace(struct PeerData *); 46 | 47 | void 48 | PeerDataDestroy(struct PeerData *,struct Iterator *); 49 | 50 | void 51 | PeerDataSelectAsSeed(struct PeerData* , struct Iterator *); 52 | 53 | void 54 | PeerDataDele(struct PeerData *, struct Iterator *); 55 | 56 | void 57 | PeerDataUpdateSeedInfo(struct PeerData *,uchar ); 58 | 59 | struct PeerData * 60 | SeedPeerSelectOne(struct Iterator *); 61 | -------------------------------------------------------------------------------- /pipe.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | #include "tknet.h" 15 | 16 | static struct PipeMap sta_PipeMap; 17 | static uint sta_PipeIDSeed = 0; 18 | 19 | void 20 | MakeConnection(struct Iterator *pa_pI0,struct Iterator *pa_pI1) 21 | { 22 | struct connection 23 | *pC0 = tkmalloc(struct connection), 24 | *pC1 = tkmalloc(struct connection); 25 | 26 | pC0->pIterator = pa_pI0; 27 | pC0->pCounterPart = pC1; 28 | ListNodeCons(&pC0->ln); 29 | 30 | pC1->pIterator = pa_pI1; 31 | pC1->pCounterPart = pC0; 32 | ListNodeCons(&pC1->ln); 33 | 34 | AddOneToListTail(pa_pI0,&pC0->ln); 35 | AddOneToListTail(pa_pI1,&pC1->ln); 36 | } 37 | 38 | static BOOL 39 | LIST_ITERATION_CALLBACK_FUNCTION(CutConnectionCallbk) 40 | { 41 | struct connection *pC0 = GET_STRUCT_ADDR_FROM_IT(pa_pINow,struct connection,ln), 42 | *pC1 = pC0->pCounterPart; 43 | 44 | ListDragOneOut(pC1->pIterator,&pC1->ln); 45 | pC0->pIterator = NULL; 46 | pC0->pCounterPart = NULL; 47 | tkfree(pC1); 48 | 49 | return pa_pINow->now == pa_pIHead->last; 50 | } 51 | 52 | static 53 | DEF_FREE_LIST_ELEMENT_CALLBACK_FUNCTION(FreeConnectionCallbk , struct connection , ln , ;) 54 | 55 | void 56 | CutConnections(struct Iterator *pa_pI) 57 | { 58 | ForEach(pa_pI,&CutConnectionCallbk,NULL); 59 | ForEach(pa_pI,&FreeConnectionCallbk,NULL); 60 | } 61 | 62 | BOOL 63 | PipeDirectOnlyTo(struct pipe *pa_pFrom,struct pipe *pa_pTo) 64 | { 65 | CutConnections(&pa_pFrom->IDirection); 66 | MakeConnection(&pa_pFrom->IDirection,&pa_pTo->IReference); 67 | return 1; 68 | } 69 | 70 | BOOL 71 | PipeDirectTo(struct pipe *pa_pFrom,struct pipe *pa_pTo) 72 | { 73 | MakeConnection(&pa_pFrom->IDirection,&pa_pTo->IReference); 74 | return 1; 75 | } 76 | 77 | void 78 | PipeDele(struct pipe *pa_pPipe) 79 | { 80 | CutConnections(&pa_pPipe->IDirection); 81 | CutConnections(&pa_pPipe->IReference); 82 | ListDragOneOut(&sta_PipeMap.IPipe,&pa_pPipe->ln); 83 | if(pa_pPipe->pFlowPa) 84 | tkfree(pa_pPipe->pFlowPa); 85 | tkfree(pa_pPipe); 86 | } 87 | 88 | static BOOL 89 | LIST_ITERATION_CALLBACK_FUNCTION(ResetPipeCallbk) 90 | { 91 | struct pipe *pPipe = GET_STRUCT_ADDR_FROM_IT(pa_pINow,struct pipe,ln); 92 | 93 | CutConnections(&pPipe->IDirection); 94 | CutConnections(&pPipe->IReference); 95 | 96 | return pa_pINow->now == pa_pIHead->last; 97 | } 98 | 99 | void 100 | PipeReset() 101 | { 102 | ForEach(&sta_PipeMap.IPipe,&ResetPipeCallbk,NULL); 103 | } 104 | 105 | void 106 | PipeModuleInit() 107 | { 108 | sta_PipeMap.IPipe = GetIterator(NULL); 109 | } 110 | 111 | DEF_FREE_LIST_ELEMENT_CALLBACK_FUNCTION(PipeDeleCallbk,struct pipe,ln, 112 | CutConnections(&pNow->IDirection); 113 | CutConnections(&pNow->IReference); 114 | if(pNow->pFlowPa) 115 | tkfree(pNow->pFlowPa); 116 | ) 117 | 118 | void 119 | PipeModuleUninit() 120 | { 121 | ForEach(&sta_PipeMap.IPipe,&PipeDeleCallbk,NULL); 122 | } 123 | 124 | static BOOL 125 | LIST_ITERATION_CALLBACK_FUNCTION(FindPipeByNameCallbk) 126 | { 127 | struct pipe *pPipe = GET_STRUCT_ADDR_FROM_IT(pa_pINow,struct pipe,ln); 128 | DEF_AND_CAST(pFpbnpa,struct FindPipeByName ,pa_else); 129 | 130 | if( strcmp(pFpbnpa->name,pPipe->name) == 0 ) 131 | { 132 | pFpbnpa->found = pPipe; 133 | return 1; 134 | } 135 | else 136 | { 137 | return pa_pINow->now == pa_pIHead->last; 138 | } 139 | } 140 | 141 | struct pipe* 142 | PipeFindByName(char *pa_pName) 143 | { 144 | struct FindPipeByName fpbnpa; 145 | fpbnpa.found = NULL; 146 | fpbnpa.name = pa_pName; 147 | 148 | ForEach( &sta_PipeMap.IPipe , &FindPipeByNameCallbk , &fpbnpa ); 149 | return fpbnpa.found; 150 | } 151 | 152 | struct pipe* 153 | PipeMap(char *pa_pName) 154 | { 155 | struct pipe* pPipe = PipeFindByName(pa_pName); 156 | 157 | if(pPipe == NULL) 158 | { 159 | pPipe = tkmalloc(struct pipe); 160 | strcpy(pPipe->name,pa_pName); 161 | pPipe->FlowCallbk = NULL; 162 | pPipe->pFlowPa = NULL; 163 | pPipe->id = ++ sta_PipeIDSeed; 164 | 165 | ListNodeCons(&pPipe->ln); 166 | pPipe->IDirection = GetIterator(NULL); 167 | pPipe->IReference = GetIterator(NULL); 168 | 169 | AddOneToListTail(&sta_PipeMap.IPipe,&pPipe->ln); 170 | } 171 | 172 | return pPipe; 173 | } 174 | 175 | static BOOL 176 | LIST_ITERATION_CALLBACK_FUNCTION(PrintPipeDirectionsCallbk) 177 | { 178 | struct connection *pC = GET_STRUCT_ADDR_FROM_IT(pa_pINow,struct connection,ln); 179 | struct pipe *pDir; 180 | BOOL end; 181 | 182 | if(pa_pINow->now == pa_pIHead->last) 183 | end = 1; 184 | else 185 | end = 0; 186 | 187 | if(pC->pCounterPart == NULL) 188 | { 189 | PROMPT(Usual,"%s%s","NULL",end?".":","); 190 | } 191 | else 192 | { 193 | pDir = GET_STRUCT_ADDR(pC->pCounterPart->pIterator,struct pipe,IReference); 194 | PROMPT(Usual,"%s%s",pDir->name,end?".":","); 195 | } 196 | 197 | return end; 198 | } 199 | 200 | static BOOL 201 | LIST_ITERATION_CALLBACK_FUNCTION(PrintPipeReferencesCallbk) 202 | { 203 | struct connection *pC = GET_STRUCT_ADDR_FROM_IT(pa_pINow,struct connection,ln); 204 | struct pipe *pRef; 205 | BOOL end; 206 | 207 | if(pa_pINow->now == pa_pIHead->last) 208 | end = 1; 209 | else 210 | end = 0; 211 | 212 | if(pC->pCounterPart == NULL) 213 | { 214 | PROMPT(Usual,"%s%s","NULL",end?".":","); 215 | return end; 216 | } 217 | else 218 | { 219 | pRef = GET_STRUCT_ADDR(pC->pCounterPart->pIterator,struct pipe,IDirection); 220 | PROMPT(Usual,"%s%s",pRef->name,end?".":","); 221 | } 222 | 223 | return end; 224 | } 225 | 226 | static BOOL 227 | LIST_ITERATION_CALLBACK_FUNCTION(PrintPipeCallbk) 228 | { 229 | struct pipe *pPipe = GET_STRUCT_ADDR_FROM_IT(pa_pINow,struct pipe,ln); 230 | 231 | PROMPT(Usual,"%d: %s",pPipe->id,pPipe->name); 232 | PROMPT(Usual," dir:"); 233 | ForEach(&pPipe->IDirection,&PrintPipeDirectionsCallbk,NULL); 234 | PROMPT(Usual," ref:"); 235 | ForEach(&pPipe->IReference,&PrintPipeReferencesCallbk,NULL); 236 | PROMPT(Usual,"\n"); 237 | 238 | return pa_pINow->now == pa_pIHead->last; 239 | } 240 | 241 | void 242 | PipeTablePrint() 243 | { 244 | PROMPT(Usual,"Pipe table:\n"); 245 | ForEach(&sta_PipeMap.IPipe,&PrintPipeCallbk,NULL); 246 | PROMPT(Usual,"\n"); 247 | } 248 | 249 | static BOOL 250 | LIST_ITERATION_CALLBACK_FUNCTION(FlowToCallbk) 251 | { 252 | struct connection *pC = GET_STRUCT_ADDR_FROM_IT(pa_pINow,struct connection,ln); 253 | struct pipe *pTo = GET_STRUCT_ADDR(pC->pCounterPart->pIterator,struct pipe,IReference); 254 | DEF_AND_CAST(pFcbkpa,struct FlowCallbkPa,pa_else); 255 | 256 | if(pTo->FlowCallbk) 257 | { 258 | pTo->FlowCallbk(pFcbkpa->pData,pFcbkpa->DataLen, 259 | pTo,pTo->pFlowPa,pFcbkpa->Else); 260 | } 261 | else 262 | //flow to a null-out pipe 263 | { 264 | ;//do nothing 265 | } 266 | 267 | return pa_pINow->now == pa_pIHead->last; 268 | } 269 | 270 | void 271 | PipeFlow(struct pipe *pa_pPipe,char *pa_pData,uint pa_DataLen,void *pa_else) 272 | { 273 | struct FlowCallbkPa fcbkpa; 274 | fcbkpa.pData = pa_pData; 275 | fcbkpa.DataLen = pa_DataLen; 276 | fcbkpa.Else = pa_else; 277 | 278 | ForEach(&pa_pPipe->IDirection,&FlowToCallbk,&fcbkpa); 279 | } 280 | 281 | static BOOL 282 | LIST_ITERATION_CALLBACK_FUNCTION(ifPipeToCallbk) 283 | { 284 | struct connection *pC = GET_STRUCT_ADDR_FROM_IT(pa_pINow,struct connection,ln); 285 | struct pipe *pDir = GET_STRUCT_ADDR(pC->pCounterPart->pIterator,struct pipe,IReference); 286 | DEF_AND_CAST(pIptPa,struct IfPipeToPa,pa_else); 287 | 288 | if(pDir == pIptPa->pTo) 289 | { 290 | pIptPa->res = 1; 291 | return 1; 292 | } 293 | else 294 | return pa_pINow->now == pa_pIHead->last; 295 | } 296 | 297 | BOOL 298 | ifPipeTo(struct pipe *pa_pFrom,struct pipe *pa_pTo) 299 | { 300 | struct IfPipeToPa iptpa; 301 | iptpa.res = 0; 302 | iptpa.pTo = pa_pTo; 303 | 304 | ForEach(&pa_pFrom->IDirection,&ifPipeToCallbk,&iptpa); 305 | return iptpa.res; 306 | } 307 | 308 | static BOOL 309 | LIST_ITERATION_CALLBACK_FUNCTION(FindPipeByIDCallbk) 310 | { 311 | struct pipe *pPipe = GET_STRUCT_ADDR_FROM_IT(pa_pINow,struct pipe,ln); 312 | DEF_AND_CAST(pFpbipa,struct FindPipeByID ,pa_else); 313 | 314 | if( pFpbipa->id == pPipe->id ) 315 | { 316 | pFpbipa->found = pPipe; 317 | return 1; 318 | } 319 | else 320 | { 321 | return pa_pINow->now == pa_pIHead->last; 322 | } 323 | } 324 | 325 | struct pipe* 326 | PipeFindByID(uint pa_ID) 327 | { 328 | struct FindPipeByID fpbipa; 329 | fpbipa.found = NULL; 330 | fpbipa.id = pa_ID; 331 | 332 | ForEach( &sta_PipeMap.IPipe , &FindPipeByIDCallbk , &fpbipa ); 333 | return fpbipa.found; 334 | } 335 | -------------------------------------------------------------------------------- /pipe.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | #include "tknet.h" 15 | 16 | #define PIPE_NAME_MAXLEN 23 17 | //Now, the max len is defined by the 18 | //longest possible name string: 19 | //"123.123.123.123/12345\0" 20 | 21 | #define FLOW_PAELSE_NAME_LEN 32 22 | 23 | struct pipe; 24 | 25 | typedef void (*PipeFlowCallbk)(char* ,uint ,struct pipe*, 26 | void* ,void*); 27 | 28 | #define FLOW_CALLBK_FUNCTION( _fun_name ) \ 29 | void _fun_name (char* pa_pData,uint pa_DataLen,struct pipe *pa_pPipe, \ 30 | void *pa_pFlowPa,void* pa_else) 31 | 32 | struct pipe 33 | { 34 | PipeFlowCallbk FlowCallbk; 35 | void *pFlowPa;//freed by pipe. 36 | char name[PIPE_NAME_MAXLEN]; 37 | uint id; 38 | struct ListNode ln; 39 | struct Iterator IDirection; 40 | struct Iterator IReference; 41 | }; 42 | 43 | struct connection 44 | { 45 | struct Iterator *pIterator; 46 | struct connection *pCounterPart; 47 | struct ListNode ln; 48 | }; 49 | 50 | struct FindPipeByName 51 | { 52 | char *name; 53 | struct pipe *found; 54 | }; 55 | 56 | struct FindPipeByID 57 | { 58 | uint id; 59 | struct pipe *found; 60 | }; 61 | 62 | struct PipeMap 63 | { 64 | struct Iterator IPipe; 65 | }; 66 | 67 | struct FlowCallbkPa 68 | { 69 | char *pData; 70 | uint DataLen; 71 | void *Else; 72 | }; 73 | 74 | struct FlowPaElse 75 | { 76 | char PaName[FLOW_PAELSE_NAME_LEN]; 77 | void *pPa; 78 | }; 79 | 80 | struct IfPipeToPa 81 | { 82 | struct pipe* pTo; 83 | BOOL res; 84 | }; 85 | 86 | void 87 | MakeConnection(struct Iterator *,struct Iterator *); 88 | 89 | void 90 | CutConnections(struct Iterator *); 91 | 92 | BOOL 93 | PipeDirectOnlyTo(struct pipe *,struct pipe *); 94 | 95 | BOOL 96 | PipeDirectTo(struct pipe *,struct pipe *); 97 | 98 | void 99 | PipeDele(struct pipe *); 100 | 101 | struct pipe* 102 | PipeFindByName(char *); 103 | 104 | struct pipe* 105 | PipeMap(char *); 106 | 107 | void 108 | PipeTablePrint(); 109 | 110 | void 111 | PipeFlow(struct pipe *,char *,uint ,void *); 112 | 113 | void 114 | PipeModuleInit(); 115 | 116 | void 117 | PipeModuleUninit(); 118 | 119 | BOOL 120 | ifPipeTo(struct pipe *,struct pipe *); 121 | 122 | struct pipe* 123 | PipeFindByID(uint); 124 | 125 | void 126 | PipeReset(); 127 | -------------------------------------------------------------------------------- /popmail.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | #include "tknet.h" 15 | 16 | STEP( ProtoPOP3Connect ) 17 | { 18 | struct POP3Proc *pProc = GET_STRUCT_ADDR( pa_pProc , struct POP3Proc , proc ); 19 | 20 | if( !SockLocateTa( pProc->pSock , pProc->HostIPVal , pProc->HostPort ) ) 21 | { 22 | return PS_CALLBK_RET_ABORT; 23 | } 24 | 25 | if( pProc->ifEnableSSL ) 26 | { 27 | SockSSLConnect( pProc->pSock ); 28 | } 29 | 30 | SockSetNonblock( pProc->pSock ); 31 | 32 | return PS_CALLBK_RET_DONE; 33 | } 34 | 35 | STEP( ProtoPOP3FirstRecv ) 36 | { 37 | struct POP3Proc *pProc = GET_STRUCT_ADDR( pa_pProc , struct POP3Proc , proc ); 38 | 39 | if( SockRead( pProc->pSock ) ) 40 | { 41 | PROMPT(Usual,"%s\n",pProc->pSock->RecvBuff); 42 | return PS_CALLBK_RET_DONE; 43 | } 44 | else if( pa_state == PS_STATE_OVERTIME ) 45 | { 46 | return PS_CALLBK_RET_ABORT; 47 | } 48 | 49 | return PS_CALLBK_RET_GO_ON; 50 | } 51 | 52 | STEP( ProtoPOP3User ) 53 | { 54 | struct POP3Proc *pProc = GET_STRUCT_ADDR( pa_pProc , struct POP3Proc , proc ); 55 | char StrBuff[POP3_PROTO_USRNAME_MAX_LEN]; 56 | strcpy( StrBuff , "USER " ); 57 | strcat( StrBuff , pProc->UsrName ); 58 | strcat( StrBuff , "\r\n" ); 59 | 60 | if( SockRead( pProc->pSock ) ) 61 | { 62 | PROMPT(Usual,"%s\n",pProc->pSock->RecvBuff); 63 | return PS_CALLBK_RET_DONE; 64 | } 65 | else if( pa_state == PS_STATE_OVERTIME || pa_state == PS_STATE_FIRST_TIME ) 66 | { 67 | PROMPT(Usual,"write: %s \n", StrBuff ); 68 | SockWrite( pProc->pSock , StrBys(StrBuff) ); 69 | } 70 | else if( pa_state == PS_STATE_LAST_TIME ) 71 | { 72 | return PS_CALLBK_RET_ABORT; 73 | } 74 | 75 | return PS_CALLBK_RET_GO_ON; 76 | } 77 | 78 | STEP( ProtoPOP3Password ) 79 | { 80 | struct POP3Proc *pProc = GET_STRUCT_ADDR( pa_pProc , struct POP3Proc , proc ); 81 | char StrBuff[POP3_PROTO_PASSWORD_MAX_LEN]; 82 | strcpy( StrBuff , "PASS " ); 83 | strcat( StrBuff , pProc->PassWord ); 84 | strcat( StrBuff , "\r\n" ); 85 | 86 | if( SockRead( pProc->pSock ) ) 87 | { 88 | PROMPT(Usual,"%s\n",pProc->pSock->RecvBuff); 89 | return PS_CALLBK_RET_DONE; 90 | } 91 | else if( pa_state == PS_STATE_OVERTIME || pa_state == PS_STATE_FIRST_TIME ) 92 | { 93 | PROMPT(Usual,"write: %s \n", StrBuff ); 94 | SockWrite( pProc->pSock , StrBys(StrBuff) ); 95 | } 96 | else if( pa_state == PS_STATE_LAST_TIME ) 97 | { 98 | return PS_CALLBK_RET_ABORT; 99 | } 100 | 101 | return PS_CALLBK_RET_GO_ON; 102 | } 103 | 104 | STEP( ProtoPOP3List ) 105 | { 106 | struct POP3Proc *pProc = GET_STRUCT_ADDR( pa_pProc , struct POP3Proc , proc ); 107 | char *pBuff; 108 | int i ; 109 | struct NetInfoMail *pNewMail; 110 | 111 | if( SockRead( pProc->pSock ) ) 112 | { 113 | pProc->ifEnterSucc = 1; 114 | 115 | PROMPT(Usual,"%s \n",pProc->pSock->RecvBuff); 116 | 117 | pBuff = pProc->pSock->RecvBuff; 118 | 119 | while(1) 120 | { 121 | pBuff = strstr( pBuff , "\r\n" ); 122 | 123 | if(pBuff != NULL && pBuff[2] != '.' ) 124 | { 125 | pBuff += 2; 126 | for(i = 0; pBuff[i] != '\r' ; i++) 127 | { 128 | if( pBuff[i] == ' ') 129 | { 130 | pBuff[i] = '\0'; 131 | i ++; 132 | break; 133 | } 134 | } 135 | 136 | pNewMail = tkmalloc( struct NetInfoMail ); 137 | ListNodeCons( &pNewMail->ln ); 138 | sscanf( pBuff ,"%d", &pNewMail->num ); 139 | pNewMail->content[0] = '\0'; 140 | AddOneToListTail( &pProc->IMailsHead , &pNewMail->ln ); 141 | 142 | pBuff += i; 143 | } 144 | else 145 | { 146 | break; 147 | } 148 | } 149 | 150 | if( pProc->IMailsHead.now != NULL ) 151 | { 152 | pProc->IRetrieveNow = GetIterator( pProc->IMailsHead.now->last ); 153 | pProc->MailContentBuff[0] = '\0'; 154 | } 155 | else 156 | { 157 | return FlagNum(6); 158 | } 159 | 160 | return PS_CALLBK_RET_DONE; 161 | } 162 | else if( pa_state == PS_STATE_OVERTIME || pa_state == PS_STATE_FIRST_TIME ) 163 | { 164 | SockWrite( pProc->pSock , StrBys("LIST\r\n") ); 165 | } 166 | else if( pa_state == PS_STATE_LAST_TIME ) 167 | { 168 | return PS_CALLBK_RET_ABORT; 169 | } 170 | 171 | return PS_CALLBK_RET_GO_ON; 172 | } 173 | 174 | static void 175 | ParseSpecialContentToSpace(char *); 176 | 177 | STEP( ProtoPOP3Retr ) 178 | { 179 | struct POP3Proc *pProc = GET_STRUCT_ADDR( pa_pProc , struct POP3Proc , proc ); 180 | struct NetInfoMail *pMail = NULL; 181 | char StrBuff[16]; 182 | char *pUsefulContent , *pUsefulContentEnd; 183 | 184 | if( pProc->IRetrieveNow.now == NULL ) 185 | { 186 | return PS_CALLBK_RET_DONE; 187 | } 188 | 189 | pMail = GET_STRUCT_ADDR_FROM_IT( &pProc->IRetrieveNow , struct NetInfoMail , ln ); 190 | 191 | if( SockRead( pProc->pSock ) ) 192 | { 193 | if( pProc->pSock->RecvBuff[0] != '+') 194 | { 195 | VCK( strlen(pProc->MailContentBuff) + strlen(pProc->pSock->RecvBuff) > SOCK_RECV_BUFF_LEN - 1 , goto nextmail; ); 196 | 197 | strcat( pProc->MailContentBuff , pProc->pSock->RecvBuff ); 198 | } 199 | else 200 | { 201 | strcpy( pProc->MailContentBuff , pProc->pSock->RecvBuff ); 202 | } 203 | 204 | pUsefulContent = pProc->MailContentBuff; 205 | pUsefulContent = strstr(pUsefulContent ,"\r\n\r\n"); 206 | 207 | if( pUsefulContent != NULL ) 208 | { 209 | pUsefulContentEnd = strstr(pUsefulContent ,"\r\n.\r\n"); 210 | 211 | if( pUsefulContentEnd != NULL ) 212 | { 213 | pUsefulContent += 4; 214 | *pUsefulContentEnd = '\0'; 215 | 216 | VCK( strlen(pUsefulContent) > MAX_MAIL_CONTENT_LEN - 1, goto nextmail;); 217 | strcpy( pMail->content , pUsefulContent ); 218 | ParseSpecialContentToSpace(pMail->content); 219 | } 220 | else 221 | { 222 | return PS_CALLBK_RET_GO_ON; 223 | } 224 | } 225 | else 226 | { 227 | return PS_CALLBK_RET_GO_ON; 228 | } 229 | 230 | nextmail: 231 | 232 | pProc->IRetrieveNow = GetIterator( pProc->IRetrieveNow.now->last ); 233 | 234 | if( pProc->IRetrieveNow.now == pProc->IMailsHead.last ) 235 | { 236 | return PS_CALLBK_RET_DONE; 237 | } 238 | else 239 | { 240 | if( pProc->Retrieves != 0 ) 241 | { 242 | pProc->Retrieves --; 243 | } 244 | 245 | if( pProc->Retrieves != 0 ) 246 | { 247 | pProc->MailContentBuff[0] = '\0'; 248 | return PS_CALLBK_RET_REDO; 249 | } 250 | else 251 | { 252 | return PS_CALLBK_RET_DONE; 253 | } 254 | } 255 | } 256 | else if( pa_state == PS_STATE_OVERTIME || pa_state == PS_STATE_FIRST_TIME ) 257 | { 258 | sprintf( StrBuff , "RETR %d\r\n" , pMail->num ); 259 | SockWrite( pProc->pSock , StrBys(StrBuff) ); 260 | PROMPT(Usual,"write: %s", StrBuff ); //No need to plus '\n', StrBuff already has. 261 | } 262 | else if( pa_state == PS_STATE_LAST_TIME ) 263 | { 264 | return PS_CALLBK_RET_ABORT; 265 | } 266 | 267 | return PS_CALLBK_RET_GO_ON; 268 | } 269 | 270 | STEP( ProtoPOP3Quit ) 271 | { 272 | struct POP3Proc *pProc = GET_STRUCT_ADDR( pa_pProc , struct POP3Proc , proc ); 273 | char StrBuff[] = "QUIT\r\n"; 274 | 275 | PROMPT(Usual,"write: %s \n", StrBuff ); 276 | SockWrite( pProc->pSock , StrBys(StrBuff) ); 277 | 278 | return PS_CALLBK_RET_DONE; 279 | } 280 | 281 | void 282 | MakeProtoPOP3Proc( struct POP3Proc *pa_pPop3Proc , const char *pa_pHostIP , ushort pa_HostPort , BOOL pa_ifEnableSSL , const char *pa_pUsrName , const char *pa_pPassWord ) 283 | { 284 | ProcessCons( &pa_pPop3Proc->proc ); 285 | PROCESS_ADD_STEP( &pa_pPop3Proc->proc , ProtoPOP3Connect , g_WaitLevel[1] ); 286 | PROCESS_ADD_STEP( &pa_pPop3Proc->proc , ProtoPOP3FirstRecv , g_WaitLevel[1] ); 287 | PROCESS_ADD_STEP( &pa_pPop3Proc->proc , ProtoPOP3User , g_WaitLevel[2] ); 288 | PROCESS_ADD_STEP( &pa_pPop3Proc->proc , ProtoPOP3Password , g_WaitLevel[2] ); 289 | PROCESS_ADD_STEP( &pa_pPop3Proc->proc , ProtoPOP3List , g_WaitLevel[2] ); 290 | PROCESS_ADD_STEP( &pa_pPop3Proc->proc , ProtoPOP3Retr , g_WaitLevel[2] ); 291 | PROCESS_ADD_STEP( &pa_pPop3Proc->proc , ProtoPOP3Quit , g_WaitLevel[0] ); 292 | 293 | pa_pPop3Proc->HostIPVal = GetIPVal( pa_pHostIP ); 294 | pa_pPop3Proc->HostPort = pa_HostPort; 295 | pa_pPop3Proc->ifEnableSSL = pa_ifEnableSSL; 296 | strcpy( pa_pPop3Proc->UsrName , pa_pUsrName ); 297 | strcpy( pa_pPop3Proc->PassWord , pa_pPassWord ); 298 | pa_pPop3Proc->IMailsHead = GetIterator(NULL); 299 | pa_pPop3Proc->IRetrieveNow = GetIterator(NULL); 300 | pa_pPop3Proc->Retrieves = 5; // maximum allowed retrieves 301 | pa_pPop3Proc->ifEnterSucc = 0; 302 | } 303 | 304 | BOOL 305 | LIST_ITERATION_CALLBACK_FUNCTION( TraceMail ) 306 | { 307 | struct NetInfoMail *pMail = GET_STRUCT_ADDR_FROM_IT( pa_pINow , struct NetInfoMail , ln); 308 | PROMPT(Usual,"mail No.%d :\n", pMail->num); 309 | StrTraceFormat(pMail->content); 310 | PROMPT(Usual,"END\n\n"); 311 | 312 | return pa_pINow->now == pa_pIHead->last; 313 | } 314 | 315 | DEF_FREE_LIST_ELEMENT_CALLBACK_FUNCTION( FreeNetInfoMail , struct NetInfoMail , ln , ; ) 316 | 317 | void 318 | POP3ProcFree( struct POP3Proc *pa_pPop3Proc ) 319 | { 320 | ForEach( &pa_pPop3Proc->IMailsHead , &FreeNetInfoMail , NULL ); 321 | ProcessFree(&pa_pPop3Proc->proc); 322 | } 323 | 324 | static void 325 | ParseSpecialContentToSpace(char *pa_pStr) 326 | { 327 | char *res; 328 | 329 | while(1) 330 | { 331 | res = strstr(pa_pStr,"=C2=A0"); 332 | //=C2=A0 represents the bytes C2 A0 333 | //which is the Unicode for non-breaking 334 | //space( ) in MIME. 335 | 336 | if(res) 337 | { 338 | res[0] = ' '; 339 | res[1] = ' '; 340 | res[2] = ' '; 341 | res[3] = ' '; 342 | res[4] = ' '; 343 | res[5] = ' '; 344 | } 345 | else 346 | { 347 | break; 348 | } 349 | } 350 | 351 | while(1) 352 | { 353 | res = strstr(pa_pStr,"\r"); 354 | if(res) 355 | { 356 | res[0] = ' '; 357 | } 358 | else 359 | { 360 | break; 361 | } 362 | } 363 | 364 | while(1) 365 | { 366 | res = strstr(pa_pStr,"\n"); 367 | if(res) 368 | { 369 | res[0] = ' '; 370 | } 371 | else 372 | { 373 | break; 374 | } 375 | } 376 | } 377 | -------------------------------------------------------------------------------- /popmail.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | #define MAX_MAIL_CONTENT_LEN 256 15 | #define POP3_PROTO_USRNAME_MAX_LEN 64 16 | #define POP3_PROTO_PASSWORD_MAX_LEN 64 17 | 18 | struct NetInfoMail 19 | { 20 | int num; 21 | char content[MAX_MAIL_CONTENT_LEN]; 22 | struct ListNode ln; 23 | }; 24 | 25 | struct POP3Proc 26 | { 27 | struct Process proc; 28 | struct Sock *pSock; 29 | int HostIPVal; 30 | ushort HostPort; 31 | BOOL ifEnableSSL; 32 | char UsrName[POP3_PROTO_USRNAME_MAX_LEN]; 33 | char PassWord[POP3_PROTO_PASSWORD_MAX_LEN]; 34 | struct Iterator IMailsHead; 35 | struct Iterator IRetrieveNow; 36 | uint Retrieves; 37 | char MailContentBuff[SOCK_RECV_BUFF_LEN]; 38 | BOOL ifEnterSucc; 39 | }; 40 | 41 | 42 | void 43 | MakeProtoPOP3Proc( struct POP3Proc* , const char* , ushort , BOOL , const char* , const char* ); 44 | 45 | void 46 | POP3ProcFree( struct POP3Proc* ); 47 | 48 | BOOL 49 | LIST_ITERATION_CALLBACK_FUNCTION( TraceMail ); 50 | 51 | EXTERN_STEP( ProtoPOP3Connect ) 52 | 53 | EXTERN_STEP( ProtoPOP3FirstRecv ) 54 | 55 | EXTERN_STEP( ProtoPOP3User ) 56 | 57 | EXTERN_STEP( ProtoPOP3Password ) 58 | -------------------------------------------------------------------------------- /relay.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | #include "tknet.h" 15 | 16 | uint g_Relays = 0; 17 | static struct Iterator sta_IRelayProc; 18 | static struct RelayProc sta_RelayProcess; 19 | 20 | struct FindRelayProcByRelayIDPa 21 | { 22 | uint RelayID; 23 | struct RelayProc *pFound; 24 | }; 25 | 26 | DEF_STRUCT_CONSTRUCTOR( RelayProc , 27 | out_cons->RelayID = 0; 28 | PeerCons(&out_cons->peer0); 29 | PeerCons(&out_cons->peer1); 30 | ProcessConsAndSetSteps(&out_cons->proc,&sta_RelayProcess.proc); 31 | out_cons->pSock = NULL; 32 | ListNodeCons(&out_cons->ln); 33 | ) 34 | 35 | static __inline void 36 | RelayTo(struct RelayProc *pa_pRelayProc,struct NetAddr *pa_pToAddr) 37 | { 38 | DEF_AND_CAST(pMsg,struct TkNetMsg,pa_pRelayProc->pSock->RecvBuff); 39 | SockLocateTa(pa_pRelayProc->pSock,htonl(pa_pToAddr->IPv4),pa_pToAddr->port); 40 | SockWrite(pa_pRelayProc->pSock,BYS(*pMsg)); 41 | } 42 | 43 | DEF_FREE_LIST_ELEMENT_SAFE_FUNCTION(FreeRelayProc,struct RelayProc,ln,;) 44 | 45 | EXTERN_STEP( Relay ) 46 | 47 | void 48 | RelayModuleInit() 49 | { 50 | sta_IRelayProc = GetIterator(NULL); 51 | 52 | ProcessCons(&sta_RelayProcess.proc); 53 | PROCESS_ADD_STEP( &sta_RelayProcess.proc , Relay , g_WaitLevel[4] ); 54 | } 55 | 56 | void 57 | RelayMuduleDestruction() 58 | { 59 | ForEach(&sta_IRelayProc,&FreeRelayProc,NULL); 60 | ProcessFree(&sta_RelayProcess.proc); 61 | } 62 | 63 | STEP( Relay ) 64 | { 65 | struct RelayProc *pRelayProc = GET_STRUCT_ADDR(pa_pProc,struct RelayProc,proc); 66 | struct NetAddr FromAddr = GetAddrFromSockAddr(&pRelayProc->pSock->AddrRecvfrom); 67 | struct NetAddr *pAddr; 68 | struct TkNetMsg SendingMsg; 69 | struct TkNetMsg *pMsg = NULL; 70 | 71 | if(pRelayProc->pSock->RecvLen > 0) 72 | { 73 | pMsg = (struct TkNetMsg*)pRelayProc->pSock->RecvBuff; 74 | } 75 | 76 | if(pMsg && pMsg->flag != TK_NET_BDG_MSG_FLAG) 77 | { 78 | if(pRelayProc->peer1.addr.port != 0) 79 | { 80 | if(ifNetAddrEqual(&FromAddr,&(pRelayProc->peer0.addr))) 81 | { 82 | RelayTo(pRelayProc,&(pRelayProc->peer1.addr)); 83 | return PS_CALLBK_RET_REDO; 84 | } 85 | else if(ifNetAddrEqual(&FromAddr,&(pRelayProc->peer1.addr))) 86 | { 87 | RelayTo(pRelayProc,&(pRelayProc->peer0.addr)); 88 | return PS_CALLBK_RET_REDO; 89 | } 90 | } 91 | else 92 | { 93 | if(ifNetAddrEqual(&FromAddr,&(pRelayProc->peer0.addr))) 94 | { 95 | 96 | SendingMsg.flag = TK_NET_BDG_MSG_FLAG; 97 | SendingMsg.msg.BdgMsg.info = BRIDGE_MSG_INFO_WAIT_RELAY; 98 | 99 | pAddr = &(pRelayProc->peer0.addr); 100 | SockLocateTa(pRelayProc->pSock,htonl(pAddr->IPv4),pAddr->port); 101 | SockWrite(pRelayProc->pSock,BYS(SendingMsg)); 102 | 103 | return PS_CALLBK_RET_REDO; 104 | } 105 | } 106 | } 107 | 108 | if(pa_state == PS_STATE_LAST_TIME) 109 | { 110 | return PS_CALLBK_RET_ABORT; 111 | } 112 | 113 | return PS_CALLBK_RET_GO_ON; 114 | } 115 | 116 | BOOL 117 | LIST_ITERATION_CALLBACK_FUNCTION(FindRelayProcByRelayID) 118 | { 119 | struct RelayProc *pRelayProc 120 | = GET_STRUCT_ADDR_FROM_IT(pa_pINow,struct RelayProc,ln); 121 | DEF_AND_CAST(pFRPBRIPa,struct FindRelayProcByRelayIDPa ,pa_else); 122 | 123 | if(pFRPBRIPa->RelayID == pRelayProc->RelayID) 124 | { 125 | pFRPBRIPa->pFound = pRelayProc; 126 | return 1; 127 | } 128 | else 129 | { 130 | return pa_pINow->now == pa_pIHead->last; 131 | } 132 | } 133 | 134 | void 135 | RelayProcNotify(struct Process *pa_) 136 | { 137 | struct RelayProc *pRelayProc = GET_STRUCT_ADDR(pa_,struct RelayProc,proc); 138 | struct Iterator IForward,INow; 139 | 140 | INow = GetIterator(&pRelayProc->ln); 141 | IForward = GetIterator(INow.now->next); 142 | FreeRelayProc(&sta_IRelayProc,&INow,&IForward,NULL); 143 | 144 | g_Relays --; 145 | PROMPT(Usual,"relay proc end\n"); 146 | } 147 | 148 | uchar 149 | RelayProcMerge(uint pa_RelayID,struct NetAddr pa_addr,struct ProcessingList *pa_pProcList,struct Iterator *pa_pINow, struct Iterator *pa_pIForward,struct Sock *pa_pSock) 150 | { 151 | struct RelayProc *pRelayProc; 152 | struct FindRelayProcByRelayIDPa FRPBRIPa; 153 | 154 | FRPBRIPa.pFound = NULL; 155 | FRPBRIPa.RelayID = pa_RelayID; 156 | ForEach(&sta_IRelayProc,&FindRelayProcByRelayID,&FRPBRIPa); 157 | 158 | if(FRPBRIPa.pFound == NULL) 159 | { 160 | pRelayProc = tkmalloc(struct RelayProc); 161 | RelayProcCons(pRelayProc); 162 | 163 | pRelayProc->RelayID = pa_RelayID; 164 | pRelayProc->peer0.addr = pa_addr; 165 | pRelayProc->pSock = pa_pSock; 166 | pRelayProc->proc.NotifyCallbk = &RelayProcNotify; 167 | 168 | AddOneToListTail(&sta_IRelayProc,&pRelayProc->ln); 169 | ProcessSafeStart(&pRelayProc->proc,pa_pProcList,pa_pINow,pa_pIForward); 170 | 171 | return RELAY_MERGE_RES_NEW_RELAY; 172 | } 173 | else if(FRPBRIPa.pFound->peer1.addr.port == 0) 174 | { 175 | FRPBRIPa.pFound->peer1.addr = pa_addr; 176 | g_Relays ++; 177 | 178 | return RELAY_MERGE_RES_MERGED; 179 | } 180 | 181 | return RELAY_MERGE_RES_WAITING; 182 | } 183 | 184 | BOOL 185 | LIST_ITERATION_CALLBACK_FUNCTION(TraceRelayProc) 186 | { 187 | struct RelayProc *pRelayProc 188 | = GET_STRUCT_ADDR_FROM_IT(pa_pINow,struct RelayProc,ln); 189 | char AddrText0[32]; 190 | char AddrText1[32]; 191 | 192 | GetAddrText(&(pRelayProc->peer0.addr),AddrText0); 193 | 194 | if(pRelayProc->peer1.addr.port == 0) 195 | { 196 | strcpy(AddrText1,"waiting"); 197 | } 198 | else 199 | { 200 | GetAddrText(&(pRelayProc->peer1.addr),AddrText1); 201 | } 202 | 203 | PROMPT(Usual,"RelayID=%d,between %s & %s \n",pRelayProc->RelayID,AddrText0,AddrText1); 204 | 205 | return pa_pINow->now == pa_pIHead->last; 206 | } 207 | 208 | void 209 | RelayProcTrace() 210 | { 211 | PROMPT(Usual,"relays(total = %d): \n",g_Relays); 212 | ForEach(&sta_IRelayProc,&TraceRelayProc,NULL); 213 | } 214 | -------------------------------------------------------------------------------- /relay.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | #define RELAY_MERGE_RES_WAITING 0 15 | #define RELAY_MERGE_RES_NEW_RELAY 1 16 | #define RELAY_MERGE_RES_MERGED 2 17 | 18 | struct RelayProc 19 | { 20 | uint RelayID; 21 | struct Peer peer0,peer1; 22 | struct Process proc; 23 | struct Sock *pSock; 24 | struct ListNode ln; 25 | }; 26 | 27 | DECLARATION_STRUCT_CONSTRUCTOR( RelayProc ) 28 | 29 | extern uint g_Relays; 30 | 31 | void 32 | RelayModuleInit(); 33 | 34 | void 35 | RelayMuduleDestruction(); 36 | 37 | uchar 38 | RelayProcMerge(uint ,struct NetAddr ,struct ProcessingList *,struct Iterator *, struct Iterator *,struct Sock *); 39 | 40 | void 41 | RelayProcTrace(); 42 | -------------------------------------------------------------------------------- /session.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | #include "tknet.h" 15 | 16 | struct TkNetMsg* 17 | UsrDatRead(struct SessionMaintainProcess *in_SesProc) 18 | { 19 | DEF_AND_CAST(pMsg,struct TkNetMsg,in_SesProc->pSock->RecvBuff); 20 | struct NetAddr FromAddr = GetAddrFromSockAddr(&in_SesProc->pSock->AddrRecvfrom); 21 | 22 | if(in_SesProc->pSock->RecvLen <= 0) 23 | { 24 | return NULL; 25 | } 26 | else if(!ifNetAddrEqual(&FromAddr,&in_SesProc->addr)) 27 | { 28 | return NULL; 29 | } 30 | else if(pMsg->flag == TK_NET_BDG_MSG_FLAG) 31 | { 32 | if(pMsg->msg.BdgMsg.info == BRIDGE_MSG_INFO_WAIT_RELAY) 33 | { 34 | PROMPT(Usual,"relay has not finished yet, " 35 | "This message can't reach the end.\n"); 36 | } 37 | 38 | return NULL; 39 | } 40 | else 41 | { 42 | return pMsg; 43 | } 44 | } 45 | 46 | static 47 | STEP( SessionMaintain ) 48 | { 49 | struct SessionMaintainProcess *pProc = 50 | GET_STRUCT_ADDR(pa_pProc,struct SessionMaintainProcess,proc); 51 | struct TkNetMsg *pRecvMsg = UsrDatRead(pProc); 52 | struct TkNetMsg SendingMsg; 53 | struct NetAddr *pAddr = &pProc->addr; 54 | struct pipe *pPipe0,*pPipe1; 55 | char AddrText[32]; 56 | 57 | if(pRecvMsg) 58 | { 59 | if(pRecvMsg->flag == SES_MAINTAIN_FLAG) 60 | { 61 | PROMPT(Usual,"~");//indicating session maintaining 62 | pProc->ifAlive = 1; 63 | 64 | goto discard; 65 | } 66 | else if(pRecvMsg->flag == SES_DAT_FLAG) 67 | { 68 | //not implemented yet. 69 | } 70 | else if(pRecvMsg->flag == SES_CMD_FLAG) 71 | { 72 | //direct net pipe to cmd pipe 73 | pPipe0 = PipeFindByName("cmd"); 74 | 75 | if(pPipe0) 76 | { 77 | if(!ifPipeTo(pProc->pPipe,pPipe0)) //make sure only pipe once 78 | { 79 | PipeDirectTo(pProc->pPipe,pPipe0); 80 | } 81 | } 82 | else 83 | { 84 | TK_EXCEPTION("finding cmd pipe."); 85 | goto discard; 86 | } 87 | 88 | //then find the net pipe to send the result back. 89 | pPipe0 = PipeFindByName("stdout"); 90 | 91 | GetAddrText(pAddr,AddrText); 92 | pPipe1 = PipeFindByName(AddrText); 93 | 94 | if(pPipe0 && pPipe1) 95 | { 96 | if(!ifPipeTo(pPipe0,pPipe1)) //make sure only pipe once 97 | { 98 | PipeDirectTo(pPipe0,pPipe1); 99 | } 100 | } 101 | else 102 | { 103 | TK_EXCEPTION("finding net or stdout pipe."); 104 | goto discard; 105 | } 106 | } 107 | else if(pRecvMsg->flag == SES_CHAT_FLAG) 108 | { 109 | //enable the other side to print recved. 110 | pPipe0 = PipeFindByName("stdout"); 111 | 112 | GetAddrText(pAddr,AddrText); 113 | pPipe1 = PipeFindByName(AddrText); 114 | 115 | if(pPipe0 && pPipe1) 116 | { 117 | if(!ifPipeTo(pPipe1,pPipe0)) //make sure only pipe once 118 | { 119 | PipeDirectTo(pPipe1,pPipe0); 120 | } 121 | } 122 | else 123 | { 124 | TK_EXCEPTION("finding net or stdout pipe."); 125 | goto discard; 126 | } 127 | 128 | //enable the other side send stdin here. 129 | pPipe0 = PipeFindByName("stdin"); 130 | 131 | if(pPipe0) 132 | { 133 | if(!ifPipeTo(pPipe0,pPipe1)) //make sure only pipe once 134 | { 135 | PipeDirectTo(pPipe0,pPipe1); 136 | } 137 | } 138 | else 139 | { 140 | TK_EXCEPTION("finding stdin pipe."); 141 | goto discard; 142 | } 143 | } 144 | else 145 | { 146 | TK_EXCEPTION("session msg flag."); 147 | goto discard; 148 | } 149 | 150 | PipeFlow(pProc->pPipe,pRecvMsg->msg.UsrDat, 151 | pRecvMsg->UsrDatLen,NULL); 152 | } 153 | 154 | discard: 155 | 156 | if(pa_state == PS_STATE_OVERTIME) 157 | { 158 | SendingMsg.flag = SES_MAINTAIN_FLAG; 159 | SockLocateTa(pProc->pSock,htonl(pAddr->IPv4),pAddr->port); 160 | SockWrite(pProc->pSock,BYS(SendingMsg)); 161 | } 162 | else if(pa_state == PS_STATE_LAST_TIME) 163 | { 164 | if(pProc->ifAlive) 165 | { 166 | pProc->ifAlive = 0; 167 | return PS_CALLBK_RET_REDO; 168 | } 169 | else 170 | { 171 | return PS_CALLBK_RET_ABORT; 172 | } 173 | } 174 | 175 | return PS_CALLBK_RET_GO_ON; 176 | } 177 | 178 | static void 179 | SessionOvertimeNotify(struct Process *pa_) 180 | { 181 | struct SessionMaintainProcess *pProc = 182 | GET_STRUCT_ADDR(pa_,struct SessionMaintainProcess,proc); 183 | 184 | ProcessTraceSteps(pa_); 185 | ProcessFree(pa_); 186 | //Do not free pProc, because pProc is passed into the flow parameter, 187 | //pipe will take care of it. 188 | 189 | PipeDele(pProc->pPipe); 190 | 191 | PROMPT(Usual,"session proc ends.\n"); 192 | } 193 | 194 | static 195 | FLOW_CALLBK_FUNCTION(SessionFlowCallbk) 196 | { 197 | DEF_AND_CAST(pProc,struct SessionMaintainProcess,pa_pFlowPa); 198 | DEF_AND_CAST(pFpe,struct FlowPaElse,pa_else); 199 | struct TkNetMsg SendingMsg; 200 | struct NetAddr *pAddr = &pProc->addr; 201 | uint now = 0; 202 | uchar *pUchar; 203 | 204 | if(pFpe && 0 == strcmp(pFpe->PaName,"uint:SET_FLAG")) 205 | { 206 | pUchar = (uchar*)pFpe->pPa; 207 | SendingMsg.flag = *pUchar; 208 | } 209 | else 210 | { 211 | SendingMsg.flag = SES_DAT_FLAG; 212 | } 213 | 214 | SockLocateTa(pProc->pSock,htonl(pAddr->IPv4),pAddr->port); 215 | 216 | while(pa_DataLen > TK_NET_DATA_LEN) 217 | { 218 | SendingMsg.UsrDatLen = TK_NET_DATA_LEN; 219 | memcpy(SendingMsg.msg.UsrDat , pa_pData + now,TK_NET_DATA_LEN); 220 | SockWrite(pProc->pSock,BYS(SendingMsg)); 221 | 222 | pa_DataLen -= TK_NET_DATA_LEN; 223 | now += TK_NET_DATA_LEN; 224 | } 225 | 226 | SendingMsg.UsrDatLen = pa_DataLen; 227 | memcpy(SendingMsg.msg.UsrDat,pa_pData + now,pa_DataLen); 228 | SockWrite(pProc->pSock,BYS(SendingMsg)); 229 | } 230 | 231 | void 232 | SessionStart(struct NetAddr pa_addr,struct Sock *pa_pSock,struct ProcessingList *pa_pProcList, 233 | struct Iterator* pa_pINow,struct Iterator *pa_pIForward) 234 | { 235 | struct SessionMaintainProcess *pProc; 236 | struct pipe *pPipe; 237 | char AddrText[PIPE_NAME_MAXLEN]; 238 | 239 | GetAddrText(&pa_addr,AddrText); 240 | pPipe = PipeFindByName(AddrText); 241 | 242 | VCK(pPipe != NULL, return); 243 | 244 | pProc = tkmalloc(struct SessionMaintainProcess); 245 | ProcessCons(&pProc->proc); 246 | pPipe = PipeMap(AddrText); 247 | 248 | pProc->proc.NotifyCallbk = &SessionOvertimeNotify; 249 | pProc->pSock = pa_pSock; 250 | pProc->addr = pa_addr; 251 | pProc->pPipe = pPipe; 252 | pProc->ifAlive = 0; 253 | 254 | pPipe->FlowCallbk = &SessionFlowCallbk; 255 | pPipe->pFlowPa = pProc; 256 | 257 | PROCESS_ADD_STEP( &pProc->proc , SessionMaintain , g_WaitLevel[3] ); 258 | ProcessSafeStart(&pProc->proc,pa_pProcList,pa_pINow,pa_pIForward); 259 | 260 | PROMPT(Usual,"session proc starts.\n"); 261 | } 262 | 263 | static 264 | FLOW_CALLBK_FUNCTION(CmdModeFlowCallbk) 265 | { 266 | struct FlowPaElse *pFpe = tkmalloc(struct FlowPaElse); 267 | uint *pSetNum = tkmalloc(uint); 268 | 269 | strcpy(pFpe->PaName,"uint:SET_FLAG"); 270 | pFpe->pPa = pSetNum; 271 | 272 | *pSetNum = SES_CMD_FLAG; 273 | 274 | PipeFlow(pa_pPipe,pa_pData,pa_DataLen,pFpe);//redirection 275 | 276 | tkfree(pSetNum); 277 | tkfree(pFpe); 278 | } 279 | 280 | void 281 | MkCmdModePipe() 282 | { 283 | struct pipe* pPipe = PipeMap("CmdMode"); 284 | pPipe->FlowCallbk = &CmdModeFlowCallbk; 285 | } 286 | 287 | static 288 | FLOW_CALLBK_FUNCTION(ChatModeFlowCallbk) 289 | { 290 | struct FlowPaElse *pFpe = tkmalloc(struct FlowPaElse); 291 | uint *pSetNum = tkmalloc(uint); 292 | 293 | strcpy(pFpe->PaName,"uint:SET_FLAG"); 294 | pFpe->pPa = pSetNum; 295 | 296 | *pSetNum = SES_CHAT_FLAG; 297 | 298 | PipeFlow(pa_pPipe,pa_pData,pa_DataLen,pFpe);//redirection 299 | 300 | tkfree(pSetNum); 301 | tkfree(pFpe); 302 | } 303 | 304 | void 305 | MkChatModePipe() 306 | { 307 | struct pipe* pPipe = PipeMap("ChatMode"); 308 | pPipe->FlowCallbk = &ChatModeFlowCallbk; 309 | } 310 | -------------------------------------------------------------------------------- /session.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | struct SessionMaintainProcess 15 | { 16 | struct Process proc; 17 | struct Sock *pSock; 18 | struct NetAddr addr; 19 | struct pipe *pPipe; 20 | BOOL ifAlive; 21 | }; 22 | 23 | void 24 | SessionStart(struct NetAddr ,struct Sock *,struct ProcessingList *,struct Iterator* ,struct Iterator *); 25 | 26 | #define SES_DAT_FLAG TK_NET_BDG_MSG_FLAG + 1 27 | #define SES_MAINTAIN_FLAG TK_NET_BDG_MSG_FLAG + 2 28 | #define SES_CMD_FLAG TK_NET_BDG_MSG_FLAG + 3 29 | #define SES_CHAT_FLAG TK_NET_BDG_MSG_FLAG + 4 30 | 31 | void 32 | MkCmdModePipe(); 33 | 34 | void 35 | MkChatModePipe(); 36 | -------------------------------------------------------------------------------- /smtpmail.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | #include "tknet.h" 15 | 16 | STEP( SMTPConnect ) 17 | { 18 | struct SMTPProc *pProc = GET_STRUCT_ADDR( pa_pProc , struct SMTPProc , proc ); 19 | 20 | 21 | struct NetAddr addr = {pProc->HostIPVal, pProc->HostPort}; 22 | char IPText[64]; 23 | GetAddrText( &addr , IPText ); 24 | printf("smtp to %s\n", IPText); 25 | 26 | if( !SockLocateTa( &pProc->Sock , pProc->HostIPVal , pProc->HostPort ) ) 27 | { 28 | return PS_CALLBK_RET_ABORT; 29 | } 30 | 31 | if( pProc->ifEnableSSL ) 32 | { 33 | SockSSLConnect( &pProc->Sock ); 34 | } 35 | 36 | SockSetNonblock( &pProc->Sock ); 37 | 38 | return PS_CALLBK_RET_DONE; 39 | } 40 | 41 | STEP( SMTPFirstRecv ) 42 | { 43 | struct SMTPProc *pProc = GET_STRUCT_ADDR( pa_pProc , struct SMTPProc , proc ); 44 | 45 | if( SockRead( &pProc->Sock ) ) 46 | { 47 | PROMPT(Usual,"return %s\n", pProc->Sock.RecvBuff ); 48 | return PS_CALLBK_RET_DONE; 49 | } 50 | else if( pa_state == PS_STATE_OVERTIME ) 51 | { 52 | return PS_CALLBK_RET_ABORT; 53 | } 54 | 55 | return PS_CALLBK_RET_GO_ON; 56 | } 57 | 58 | STEP( SMTPHello ) 59 | { 60 | struct SMTPProc *pProc = GET_STRUCT_ADDR( pa_pProc , struct SMTPProc , proc ); 61 | char StrBuff[] = "HELO you\r\n"; 62 | 63 | if( SockRead( &pProc->Sock ) ) 64 | { 65 | PROMPT(Usual,"return %s\n", pProc->Sock.RecvBuff ); 66 | return PS_CALLBK_RET_DONE; 67 | } 68 | else if( pa_state == PS_STATE_OVERTIME || pa_state == PS_STATE_FIRST_TIME ) 69 | { 70 | PROMPT(Usual,"write: %s \n", StrBuff ); 71 | SockWrite( &pProc->Sock , StrBys(StrBuff) ); 72 | } 73 | else if( pa_state == PS_STATE_LAST_TIME ) 74 | { 75 | return PS_CALLBK_RET_ABORT; 76 | } 77 | 78 | return PS_CALLBK_RET_GO_ON; 79 | } 80 | 81 | STEP( SMTPStartAuth ) 82 | { 83 | struct SMTPProc *pProc = GET_STRUCT_ADDR( pa_pProc , struct SMTPProc , proc ); 84 | char StrBuff[] = "AUTH LOGIN\r\n"; 85 | 86 | if( SockRead( &pProc->Sock ) ) 87 | { 88 | PROMPT(Usual,"return %s\n", pProc->Sock.RecvBuff ); 89 | return PS_CALLBK_RET_DONE; 90 | } 91 | else if( pa_state == PS_STATE_OVERTIME || pa_state == PS_STATE_FIRST_TIME ) 92 | { 93 | PROMPT(Usual,"write: %s \n", StrBuff ); 94 | SockWrite( &pProc->Sock , StrBys(StrBuff) ); 95 | } 96 | else if( pa_state == PS_STATE_LAST_TIME ) 97 | { 98 | return PS_CALLBK_RET_ABORT; 99 | } 100 | 101 | return PS_CALLBK_RET_GO_ON; 102 | } 103 | 104 | STEP( SMTPUsrName ) 105 | { 106 | struct SMTPProc *pProc = GET_STRUCT_ADDR( pa_pProc , struct SMTPProc , proc ); 107 | char Base64Buff[SMTP_PROTO_USRNAME_MAX_LEN]; 108 | 109 | if( SockRead( &pProc->Sock ) ) 110 | { 111 | PROMPT(Usual,"return %s\n", pProc->Sock.RecvBuff ); 112 | return PS_CALLBK_RET_DONE; 113 | } 114 | else if( pa_state == PS_STATE_OVERTIME || pa_state == PS_STATE_FIRST_TIME ) 115 | { 116 | Base64Encode( pProc->UsrName, strlen(pProc->UsrName) , Base64Buff ); 117 | PROMPT(Usual,"write %s \n",Base64Buff); 118 | strcat(Base64Buff,"\r\n"); 119 | SockWrite( &pProc->Sock , StrBys(Base64Buff) ); 120 | } 121 | else if( pa_state == PS_STATE_LAST_TIME ) 122 | { 123 | return PS_CALLBK_RET_ABORT; 124 | } 125 | 126 | return PS_CALLBK_RET_GO_ON; 127 | } 128 | 129 | STEP( SMTPPassWord ) 130 | { 131 | struct SMTPProc *pProc = GET_STRUCT_ADDR( pa_pProc , struct SMTPProc , proc ); 132 | char Base64Buff[SMTP_PROTO_PASSWORD_MAX_LEN]; 133 | 134 | if( SockRead( &pProc->Sock ) ) 135 | { 136 | PROMPT(Usual,"return %s\n", pProc->Sock.RecvBuff ); 137 | return PS_CALLBK_RET_DONE; 138 | } 139 | else if( pa_state == PS_STATE_OVERTIME || pa_state == PS_STATE_FIRST_TIME ) 140 | { 141 | Base64Encode( pProc->PassWord, strlen(pProc->PassWord) , Base64Buff ); 142 | PROMPT(Usual,"write %s \n",Base64Buff); 143 | strcat(Base64Buff,"\r\n"); 144 | SockWrite( &pProc->Sock , StrBys(Base64Buff) ); 145 | } 146 | else if( pa_state == PS_STATE_LAST_TIME ) 147 | { 148 | return PS_CALLBK_RET_ABORT; 149 | } 150 | 151 | return PS_CALLBK_RET_GO_ON; 152 | } 153 | 154 | STEP( SMTPMailFrom ) 155 | { 156 | struct SMTPProc *pProc = GET_STRUCT_ADDR( pa_pProc , struct SMTPProc , proc ); 157 | char StrBuff[ SMTP_PROTO_MAIL_ADDR_MAX_LEN + 12 ]; 158 | 159 | if( SockRead( &pProc->Sock ) ) 160 | { 161 | PROMPT(Usual,"return %s\n", pProc->Sock.RecvBuff ); 162 | return PS_CALLBK_RET_DONE; 163 | } 164 | else if( pa_state == PS_STATE_OVERTIME || pa_state == PS_STATE_FIRST_TIME ) 165 | { 166 | sprintf(StrBuff , "MAIL FROM:<%s>\r\n",pProc->MailAddr); 167 | PROMPT(Usual,"write: %s \n", StrBuff ); 168 | SockWrite( &pProc->Sock , StrBys(StrBuff) ); 169 | } 170 | else if( pa_state == PS_STATE_LAST_TIME ) 171 | { 172 | return PS_CALLBK_RET_ABORT; 173 | } 174 | 175 | return PS_CALLBK_RET_GO_ON; 176 | } 177 | 178 | STEP( SMTPRcptTo ) 179 | { 180 | struct SMTPProc *pProc = GET_STRUCT_ADDR( pa_pProc , struct SMTPProc , proc ); 181 | char StrBuff[ SMTP_PROTO_MAIL_ADDR_MAX_LEN + 12 ]; 182 | 183 | if( SockRead( &pProc->Sock ) ) 184 | { 185 | PROMPT(Usual,"return %s\n", pProc->Sock.RecvBuff ); 186 | return PS_CALLBK_RET_DONE; 187 | } 188 | else if( pa_state == PS_STATE_OVERTIME || pa_state == PS_STATE_FIRST_TIME ) 189 | { 190 | sprintf(StrBuff , "RCPT TO:<%s>\r\n",pProc->MailAddr); 191 | PROMPT(Usual,"write: %s \n", StrBuff ); 192 | SockWrite( &pProc->Sock , StrBys(StrBuff) ); 193 | } 194 | else if( pa_state == PS_STATE_LAST_TIME ) 195 | { 196 | return PS_CALLBK_RET_ABORT; 197 | } 198 | 199 | return PS_CALLBK_RET_GO_ON; 200 | } 201 | 202 | STEP( SMTPData ) 203 | { 204 | struct SMTPProc *pProc = GET_STRUCT_ADDR( pa_pProc , struct SMTPProc , proc ); 205 | char StrBuff[] = "DATA\r\nSubject: t.k. net\r\n"; 206 | 207 | if( SockRead( &pProc->Sock ) ) 208 | { 209 | PROMPT(Usual,"return %s\n", pProc->Sock.RecvBuff ); 210 | return PS_CALLBK_RET_DONE; 211 | } 212 | else if( pa_state == PS_STATE_OVERTIME || pa_state == PS_STATE_FIRST_TIME ) 213 | { 214 | PROMPT(Usual,"write: %s \n", StrBuff ); 215 | SockWrite( &pProc->Sock , StrBys(StrBuff) ); 216 | } 217 | else if( pa_state == PS_STATE_LAST_TIME ) 218 | { 219 | return PS_CALLBK_RET_ABORT; 220 | } 221 | 222 | return PS_CALLBK_RET_GO_ON; 223 | } 224 | 225 | STEP( SMTPTitle ) 226 | { 227 | struct SMTPProc *pProc = GET_STRUCT_ADDR( pa_pProc , struct SMTPProc , proc ); 228 | char StrBuff[ SMTP_PROTO_MAIL_ADDR_MAX_LEN + 12 ]; 229 | 230 | sprintf(StrBuff , "FROM:tknet<%s>\r\n",pProc->MailAddr); 231 | PROMPT(Usual,"write: %s \n", StrBuff ); 232 | SockWrite( &pProc->Sock , StrBys(StrBuff) ); 233 | 234 | sprintf(StrBuff , "TO:tknet<%s>\r\n",pProc->MailAddr); 235 | PROMPT(Usual,"write: %s \n", StrBuff ); 236 | SockWrite( &pProc->Sock , StrBys(StrBuff) ); 237 | 238 | return PS_CALLBK_RET_DONE; 239 | } 240 | 241 | STEP( SMTPContent ) 242 | { 243 | struct SMTPProc *pProc = GET_STRUCT_ADDR( pa_pProc , struct SMTPProc , proc ); 244 | char StrBuff[ MAX_MAIL_CONTENT_LEN + 8 ]; 245 | 246 | if( SockRead( &pProc->Sock ) ) 247 | { 248 | PROMPT(Usual,"return %s\n", pProc->Sock.RecvBuff ); 249 | return PS_CALLBK_RET_DONE; 250 | } 251 | else if( pa_state == PS_STATE_OVERTIME || pa_state == PS_STATE_FIRST_TIME ) 252 | { 253 | sprintf(StrBuff , "\r\n%s\r\n.\r\n",pProc->SendBuff); 254 | PROMPT(Usual,"write: %s \n", StrBuff ); 255 | SockWrite( &pProc->Sock , StrBys(StrBuff) ); 256 | } 257 | else if( pa_state == PS_STATE_LAST_TIME ) 258 | { 259 | return PS_CALLBK_RET_ABORT; 260 | } 261 | 262 | return PS_CALLBK_RET_GO_ON; 263 | } 264 | 265 | STEP( SMTPQuit ) 266 | { 267 | struct SMTPProc *pProc = GET_STRUCT_ADDR( pa_pProc , struct SMTPProc , proc ); 268 | char StrBuff[] = "QUIT\r\n"; 269 | 270 | if( SockRead( &pProc->Sock ) ) 271 | { 272 | PROMPT(Usual,"return %s\n", pProc->Sock.RecvBuff ); 273 | return PS_CALLBK_RET_DONE; 274 | } 275 | else if( pa_state == PS_STATE_OVERTIME || pa_state == PS_STATE_FIRST_TIME ) 276 | { 277 | PROMPT(Usual,"write: %s \n", StrBuff ); 278 | SockWrite( &pProc->Sock , StrBys(StrBuff) ); 279 | } 280 | else if( pa_state == PS_STATE_LAST_TIME ) 281 | { 282 | return PS_CALLBK_RET_ABORT; 283 | } 284 | 285 | return PS_CALLBK_RET_GO_ON; 286 | } 287 | 288 | void 289 | SMTPProcMake( struct SMTPProc *pa_pSMTPProc , const char *pa_pHostIPText , ushort pa_HostPort , BOOL pa_ifEnableSSL , const char *pa_pUsrName , const char *pa_pPassWord , const char *pa_pMailAddress , const char *pa_pSendBuff ) 290 | { 291 | ProcessCons( &pa_pSMTPProc->proc ); 292 | PROCESS_ADD_STEP( &pa_pSMTPProc->proc , SMTPConnect , g_WaitLevel[1] ); 293 | PROCESS_ADD_STEP( &pa_pSMTPProc->proc , SMTPFirstRecv , g_WaitLevel[1] ); 294 | PROCESS_ADD_STEP( &pa_pSMTPProc->proc , SMTPHello , g_WaitLevel[1] ); 295 | PROCESS_ADD_STEP( &pa_pSMTPProc->proc , SMTPStartAuth , g_WaitLevel[2] ); 296 | PROCESS_ADD_STEP( &pa_pSMTPProc->proc , SMTPUsrName , g_WaitLevel[2] ); 297 | PROCESS_ADD_STEP( &pa_pSMTPProc->proc , SMTPPassWord , g_WaitLevel[2] ); 298 | PROCESS_ADD_STEP( &pa_pSMTPProc->proc , SMTPMailFrom , g_WaitLevel[2] ); 299 | PROCESS_ADD_STEP( &pa_pSMTPProc->proc , SMTPRcptTo , g_WaitLevel[2] ); 300 | PROCESS_ADD_STEP( &pa_pSMTPProc->proc , SMTPData , g_WaitLevel[2] ); 301 | PROCESS_ADD_STEP( &pa_pSMTPProc->proc , SMTPTitle , g_WaitLevel[2] ); 302 | PROCESS_ADD_STEP( &pa_pSMTPProc->proc , SMTPContent , g_WaitLevel[2] ); 303 | PROCESS_ADD_STEP( &pa_pSMTPProc->proc , SMTPQuit , g_WaitLevel[2] ); 304 | 305 | SockOpen( &pa_pSMTPProc->Sock , TCP , 0 ); 306 | 307 | pa_pSMTPProc->HostIPVal = GetIPVal( pa_pHostIPText ); 308 | pa_pSMTPProc->HostPort = pa_HostPort; 309 | pa_pSMTPProc->ifEnableSSL = pa_ifEnableSSL; 310 | 311 | strcpy( pa_pSMTPProc->UsrName , pa_pUsrName ); 312 | strcpy( pa_pSMTPProc->PassWord , pa_pPassWord ); 313 | strcpy( pa_pSMTPProc->MailAddr , pa_pMailAddress ); 314 | strcpy( pa_pSMTPProc->SendBuff , pa_pSendBuff ); 315 | } 316 | -------------------------------------------------------------------------------- /smtpmail.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | #define SMTP_PROTO_USRNAME_MAX_LEN POP3_PROTO_USRNAME_MAX_LEN 15 | #define SMTP_PROTO_PASSWORD_MAX_LEN POP3_PROTO_PASSWORD_MAX_LEN 16 | #define SMTP_PROTO_MAIL_ADDR_MAX_LEN 64 17 | 18 | struct SMTPProc 19 | { 20 | struct Process proc; 21 | struct Sock Sock; 22 | int HostIPVal; 23 | ushort HostPort; 24 | BOOL ifEnableSSL; 25 | char UsrName[SMTP_PROTO_USRNAME_MAX_LEN]; 26 | char PassWord[SMTP_PROTO_PASSWORD_MAX_LEN]; 27 | char MailAddr[SMTP_PROTO_MAIL_ADDR_MAX_LEN]; 28 | char SendBuff[MAX_MAIL_CONTENT_LEN]; 29 | }; 30 | 31 | void 32 | SMTPProcMake( struct SMTPProc * , const char * , ushort , BOOL , const char * , const char * , const char * , const char * ); 33 | -------------------------------------------------------------------------------- /sock.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | #include "tknet.h" 15 | 16 | void 17 | SockInit() 18 | { 19 | WSAINIT; 20 | } 21 | 22 | void 23 | SockDestory() 24 | { 25 | WSACLEAN; 26 | } 27 | 28 | void 29 | SockSSLConnect( struct Sock* out_sock ) 30 | { 31 | #ifdef TK_CONFIG_SOCK_SSL_ENABLE 32 | SSL_CTX* ctx; 33 | SSL* ssl; 34 | 35 | SSL_load_error_strings(); 36 | VCK( SSL_library_init() != 1 ,return); 37 | 38 | ctx = SSL_CTX_new (SSLv3_client_method()); 39 | VCK( ctx == NULL ,return); 40 | ssl = SSL_new (ctx); 41 | VCK( ssl == NULL ,return); 42 | 43 | VCK( SSL_set_fd ( ssl, out_sock->socket ) != 1 , return); 44 | //enable socket SSL 45 | 46 | VCK( SSL_connect (ssl) != 1 , 47 | TK_EXCEPTION("SSLConnect failed or be shutdown"); 48 | return); 49 | //connect SSL 50 | 51 | out_sock->ctx = ctx; 52 | out_sock->ssl = ssl; 53 | #endif 54 | } 55 | 56 | // 'pa_port' is discarded when use TCP 57 | int 58 | SockOpen(struct Sock* out_sock , int pa_proto , ushort pa_port) 59 | { 60 | int res; 61 | VCK( (out_sock->socket = socket(AF_INET, pa_proto ,0)) 62 | SOCK_ERROR_CDT , WSACLEAN; return 0 ); 63 | 64 | if( pa_proto == UDP ) 65 | { 66 | out_sock->AddrMe.sin_family = AF_INET; 67 | out_sock->AddrMe.sin_port = htons(pa_port); 68 | out_sock->AddrMe.sin_addr.s_addr = htonl(INADDR_ANY); 69 | //since INADDR_ANY is defined in host byte order , 70 | //it need to be converted to network byte order. 71 | 72 | res = bind( out_sock->socket ,(struct sockaddr*)&out_sock->AddrMe , 73 | sizeof(struct sockaddr_in)); 74 | 75 | VCK( res SOCK_ERROR_CDT ,return 0 ); 76 | } 77 | 78 | out_sock->proto = pa_proto; 79 | 80 | #ifdef TK_CONFIG_SOCK_SSL_ENABLE 81 | out_sock->ctx = NULL; 82 | out_sock->ssl = NULL; 83 | #endif 84 | 85 | return 1; 86 | } 87 | 88 | void 89 | GetIPTextAndPort(struct sockaddr_in* in_addr , ushort* out_pPort , char* pa_pBuff ) 90 | { 91 | char* pStatBuff; 92 | 93 | if( out_pPort ) 94 | { 95 | *out_pPort = ntohs(in_addr->sin_port); 96 | } 97 | 98 | pStatBuff = (char*)inet_ntoa(in_addr->sin_addr); 99 | //for implementation to support IPv6 , 100 | //inet_ntoa(), inet_aton(), inet_addr() are deprecated. 101 | 102 | strcpy( pa_pBuff , pStatBuff ); 103 | } 104 | 105 | uint GetIPVal(const char* in_text) 106 | { 107 | //for implementation to support IPv6 , 108 | //inet_ntoa(), inet_aton(), inet_addr() are deprecated. 109 | 110 | return inet_addr(in_text); 111 | } 112 | 113 | //when choosing UDP , we can call this function repeatedly. 114 | //However , TCP socket must do connect function only once. 115 | int 116 | SockLocateTa( struct Sock* pa_sock , uint in_IPVal , ushort pa_port ) 117 | { 118 | pa_sock->AddrTa.sin_family = AF_INET; 119 | pa_sock->AddrTa.sin_port = htons(pa_port); 120 | pa_sock->AddrTa.sin_addr.s_addr = in_IPVal; 121 | 122 | if( pa_sock->proto == TCP ) 123 | { 124 | VCK( connect( pa_sock->socket , (struct sockaddr*)&pa_sock->AddrTa , 125 | sizeof( struct sockaddr_in)) SOCK_ERROR_CDT , 126 | return 0); 127 | } 128 | 129 | return 1; 130 | } 131 | 132 | void 133 | SockWrite( struct Sock* pa_sock , struct Bys pa_bys ) 134 | { 135 | #ifdef TK_CONFIG_SOCK_SSL_ENABLE 136 | if( pa_sock->ssl != NULL ) 137 | { 138 | SSL_write( pa_sock->ssl , pa_bys.pBytes , pa_bys.len ); 139 | }else 140 | #endif 141 | if( pa_sock->proto == TCP ) 142 | { 143 | VCK( send(pa_sock->socket,pa_bys.pBytes,pa_bys.len,0) SOCK_ERROR_CDT, 144 | return ); 145 | } 146 | else if( pa_sock->proto == UDP ) 147 | { 148 | VCK( sendto(pa_sock->socket,pa_bys.pBytes,pa_bys.len,0, 149 | (struct sockaddr*)&pa_sock->AddrTa, 150 | sizeof( struct sockaddr_in ) ) SOCK_ERROR_CDT, 151 | return ); 152 | } 153 | } 154 | 155 | __inline uint 156 | SockGetLastErr() 157 | { 158 | #if defined( __GNUC__ ) && defined( __linux__ ) 159 | return errno; 160 | #elif defined _MSC_VER 161 | return WSAGetLastError(); 162 | #endif 163 | } 164 | 165 | BOOL 166 | SockRead( struct Sock* pa_sock ) 167 | { 168 | int res; 169 | BOOL ret; 170 | uint alen; 171 | 172 | #ifdef TK_CONFIG_SOCK_SSL_ENABLE 173 | int SSL_err_res; 174 | 175 | if( pa_sock->ssl != NULL ) 176 | { 177 | res = SSL_read( pa_sock->ssl , pa_sock->RecvBuff , SOCK_RECV_BUFF_LEN ); 178 | SSL_err_res = SSL_get_error( pa_sock->ssl , res ); 179 | 180 | if( res < 0 && SSL_err_res == SSL_ERROR_WANT_READ ) 181 | { 182 | ret = 0; 183 | } 184 | else 185 | { 186 | ret = 1; 187 | } 188 | 189 | }else 190 | #endif 191 | { 192 | if( pa_sock->proto == TCP ) 193 | { 194 | res = recv(pa_sock->socket , pa_sock->RecvBuff , SOCK_RECV_BUFF_LEN , 0); 195 | } 196 | else if( pa_sock->proto == UDP ) 197 | { 198 | alen = sizeof( struct sockaddr_in ); 199 | res = recvfrom( pa_sock->socket , pa_sock->RecvBuff , 200 | SOCK_RECV_BUFF_LEN , 0 , 201 | (struct sockaddr*)&pa_sock->AddrRecvfrom , &alen); 202 | } 203 | else 204 | { 205 | TK_EXCEPTION( Sock Proto ); 206 | res = 0; 207 | } 208 | 209 | #if defined( __GNUC__ ) && defined( __linux__ ) 210 | if( res < 0 && 211 | ( SockGetLastErr() == EAGAIN || SockGetLastErr() == EWOULDBLOCK ) 212 | ) 213 | //when the socket is non-blocking in which case the value -1 is 214 | //returned and the external variable errno is set to EAGAIN or EWOULDBLOCK. 215 | 216 | #elif defined _MSC_VER 217 | if( res < 0 && SockGetLastErr() == WSAEWOULDBLOCK ) 218 | 219 | #endif 220 | { 221 | ret = 0; 222 | } 223 | else 224 | { 225 | ret = 1; 226 | } 227 | } 228 | 229 | if(ret == 0) 230 | { 231 | // we need to let res be 0 so that in this 232 | //case that non-block sock waiting for 233 | //message is not regarded as an error. 234 | res = 0; 235 | } 236 | 237 | VCK( res >= SOCK_RECV_BUFF_LEN , res = SOCK_RECV_BUFF_LEN - 1 ); 238 | 239 | VCK( res < 0 , res = 0; ); 240 | pa_sock->RecvBuff[res] = '\0'; 241 | pa_sock->RecvLen = res; 242 | 243 | return ret; 244 | } 245 | 246 | void 247 | SockSetNonblock( struct Sock* pa_sock ) 248 | { 249 | #if defined( __GNUC__ ) && defined( __linux__ ) 250 | fcntl( pa_sock->socket , F_SETFL, O_NONBLOCK); 251 | #elif defined _MSC_VER 252 | int Mode = 1; 253 | ioctlsocket( pa_sock->socket ,FIONBIO, (u_long FAR*) &Mode); 254 | #endif 255 | } 256 | 257 | void 258 | SockGetLocalIP( void (*Callback)(char* ,void*) , void* pa_else ) 259 | { 260 | char buff[32]; 261 | 262 | #if defined( __GNUC__ ) && defined( __linux__ ) 263 | struct ifaddrs *ifAddrStruct=NULL; 264 | struct ifaddrs *ifa=NULL; 265 | 266 | getifaddrs(&ifAddrStruct); 267 | 268 | for (ifa = ifAddrStruct; ifa != NULL; ifa = ifa->ifa_next) 269 | { 270 | GetIPTextAndPort((struct sockaddr_in *)ifa->ifa_addr , 271 | NULL , buff ); 272 | Callback( buff , pa_else ); 273 | } 274 | 275 | if (ifAddrStruct!=NULL) 276 | freeifaddrs(ifAddrStruct); 277 | 278 | #elif defined _MSC_VER 279 | char HostName[128]; 280 | struct hostent *pHostent; 281 | struct in_addr AddrRes; 282 | int i; 283 | 284 | gethostname( HostName , sizeof( HostName ) ); 285 | pHostent = gethostbyname(HostName); 286 | 287 | for ( i = 0; pHostent->h_addr_list[i] != 0; i++ ) 288 | { 289 | memcpy(&AddrRes, pHostent->h_addr_list[i], sizeof(struct in_addr)); 290 | memcpy( buff , inet_ntoa(AddrRes) , strlen(inet_ntoa(AddrRes)) + 1 ); 291 | Callback( buff , pa_else ); 292 | } 293 | #endif 294 | } 295 | 296 | void 297 | SockClose( struct Sock* pa_sock ) 298 | { 299 | #if defined( __GNUC__ ) && defined( __linux__ ) 300 | shutdown( pa_sock->socket , SHUT_RDWR ); 301 | close( pa_sock->socket ); 302 | #elif defined _MSC_VER 303 | shutdown( pa_sock->socket , SD_BOTH ); 304 | closesocket( pa_sock->socket ); 305 | #endif 306 | 307 | #ifdef TK_CONFIG_SOCK_SSL_ENABLE 308 | if( pa_sock->ssl != NULL ) 309 | { 310 | SSL_shutdown(pa_sock->ssl); 311 | SSL_free(pa_sock->ssl); 312 | SSL_CTX_free(pa_sock->ctx); 313 | pa_sock->ssl = NULL; 314 | pa_sock->ctx = NULL; 315 | } 316 | #endif 317 | } 318 | -------------------------------------------------------------------------------- /sock.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | #if defined( __GNUC__ ) && defined( __linux__ ) 15 | 16 | #include 17 | #include 18 | #include 19 | #include //declaration of function fcntl 20 | #include //get last erro value error 21 | #include //declarations to get local IP address 22 | #include //close() declaration to close socket 23 | 24 | typedef int SOCKVAL; 25 | #define SOCK_ERROR_CDT < 0 26 | #define WSAINIT 27 | #define WSACLEAN 28 | 29 | #elif defined _MSC_VER 30 | 31 | #ifdef TK_CONFIG_SOCK_SSL_ENABLE 32 | #pragma comment(lib,"libeay32.lib" ) 33 | #pragma comment(lib,"ssleay32.lib" ) 34 | #endif 35 | 36 | #undef BOOL 37 | #include 38 | #pragma comment(lib,"ws2_32.lib") 39 | 40 | typedef SOCKET SOCKVAL; 41 | #define SOCK_ERROR_CDT == SOCKET_ERROR 42 | #define WSACLEAN WSACleanup() 43 | #define WSAINIT WSADATA wsa ; \ 44 | WSAStartup(MAKEWORD(2,2), &wsa) 45 | 46 | #endif 47 | 48 | #ifdef TK_CONFIG_SOCK_SSL_ENABLE 49 | 50 | #include 51 | #include 52 | 53 | #define CERTF "client.pem" 54 | #define KEYF "client.key" 55 | #define CACERT "ca.pem" 56 | 57 | #endif 58 | 59 | #define SOCK_RECV_BUFF_LEN 2048 60 | 61 | #define UDP SOCK_DGRAM 62 | #define TCP SOCK_STREAM 63 | 64 | struct Sock 65 | { 66 | struct sockaddr_in AddrTa,AddrMe,AddrRecvfrom; 67 | SOCKVAL socket; 68 | int proto; 69 | uint RecvLen; 70 | char RecvBuff[ SOCK_RECV_BUFF_LEN ]; 71 | 72 | #ifdef TK_CONFIG_SOCK_SSL_ENABLE 73 | SSL_CTX *ctx; 74 | SSL *ssl; 75 | #endif 76 | }; 77 | 78 | void 79 | SockInit(); 80 | 81 | void 82 | SockDestory(); 83 | 84 | void 85 | SockSSLConnect( struct Sock* ); 86 | 87 | int 88 | SockOpen(struct Sock* , int , ushort); 89 | 90 | void 91 | GetIPTextAndPort(struct sockaddr_in* , ushort* , char* ); 92 | 93 | int 94 | SockLocateTa( struct Sock* , uint, ushort ); 95 | 96 | uint 97 | GetIPVal(const char*); 98 | 99 | void 100 | SockWrite( struct Sock* , struct Bys ); 101 | 102 | uint 103 | SockGetLastErr(); 104 | 105 | BOOL 106 | SockRead( struct Sock* ); 107 | 108 | void 109 | SockSetNonblock( struct Sock* ); 110 | 111 | void 112 | SockGetLocalIP( void (*Callback)(char* ,void*) , void* ); 113 | 114 | void 115 | SockClose( struct Sock* pa_sock ); 116 | -------------------------------------------------------------------------------- /stun.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | #include "tknet.h" 15 | 16 | #define OPT_MAPADDR_RES 0 17 | #define OPT_CHANGEADDR_RES 1 18 | 19 | struct NetAddr sta_MapAddrRes; 20 | struct NetAddr sta_ChangeAddrRes; 21 | 22 | int 23 | StunFormulateRequest(struct StunHead* out_head) 24 | { 25 | uint MagicCookie = tkGetRandom(); 26 | out_head->type = htons(0x0001); 27 | out_head->length = 0; 28 | out_head->transId1 = htonl(MagicCookie); 29 | out_head->transId2 = tkGetRandom(); 30 | out_head->transId3 = tkGetRandom(); 31 | out_head->transId4 = tkGetRandom(); 32 | 33 | return MagicCookie; 34 | } 35 | 36 | int 37 | StunFormulateChangeRequest(struct ChangeRequest* out_head , uchar pa_opt) 38 | { 39 | uint MagicCookie = tkGetRandom(); 40 | out_head->head.type = htons(0x0001); 41 | out_head->head.length = htons(0x0008); 42 | out_head->head.transId1 = htonl(MagicCookie); 43 | out_head->type = htons(0x0003); 44 | out_head->length = htons(0x0004); 45 | 46 | switch( pa_opt ) 47 | { 48 | case STUN_CHANGE_BOTH_IP_PORT: 49 | out_head->value = htonl(0x6); 50 | break; 51 | 52 | case STUN_CHANGE_IP: 53 | out_head->value = htonl(0x4); 54 | break; 55 | 56 | case STUN_CHANGE_PORT: 57 | out_head->value = htonl(0x2); 58 | break; 59 | 60 | default: 61 | TK_EXCEPTION("STUN option"); 62 | } 63 | 64 | return MagicCookie; 65 | } 66 | 67 | static void 68 | SetPortRes( uchar pa_ResTypeOpt , ushort pa_port ) 69 | { 70 | if(pa_ResTypeOpt == OPT_MAPADDR_RES) 71 | { 72 | VCK( sta_MapAddrRes.port != 0 && sta_MapAddrRes.port != pa_port ,;); 73 | sta_MapAddrRes.port = pa_port; 74 | } 75 | else if(pa_ResTypeOpt == OPT_CHANGEADDR_RES) 76 | { 77 | VCK( sta_ChangeAddrRes.port != 0 && sta_ChangeAddrRes.port != pa_port ,;); 78 | sta_ChangeAddrRes.port = pa_port; 79 | } 80 | else 81 | { 82 | TK_EXCEPTION("ResTypeOpt"); 83 | } 84 | } 85 | 86 | static void 87 | SetIPRes( uchar pa_ResTypeOpt , uint pa_IPVal ) 88 | { 89 | if(pa_ResTypeOpt == OPT_MAPADDR_RES) 90 | { 91 | VCK( sta_MapAddrRes.IPv4 != 0 && sta_MapAddrRes.IPv4 != pa_IPVal ,;); 92 | sta_MapAddrRes.IPv4 = pa_IPVal; 93 | } 94 | else if(pa_ResTypeOpt == OPT_CHANGEADDR_RES) 95 | { 96 | VCK( sta_ChangeAddrRes.IPv4 != 0 && sta_ChangeAddrRes.IPv4 != pa_IPVal ,;); 97 | sta_ChangeAddrRes.IPv4 = pa_IPVal; 98 | } 99 | else 100 | { 101 | TK_EXCEPTION("ResTypeOpt"); 102 | } 103 | } 104 | 105 | static void 106 | StunGetValue(ushort pa_attr, uint pa_i , int pa_val , uint pa_MagicCookie) 107 | { 108 | if(pa_attr == 0x0001) 109 | { 110 | //MAPPED-ADDRESS 111 | switch( pa_i ) 112 | { 113 | case 0: 114 | VCK( pa_val>>16 != 0x1 , break; );//not IPv4 115 | SetPortRes(OPT_MAPADDR_RES,(ushort)(pa_val & 0xffff)); 116 | break; 117 | case 1: 118 | SetIPRes(OPT_MAPADDR_RES,pa_val); 119 | break; 120 | 121 | default: 122 | break; 123 | } 124 | } 125 | else if( pa_attr == 0x8020 || pa_attr == 0x0020 ) 126 | { 127 | //XOR-MAPPED-ADDRESS 128 | switch( pa_i ) 129 | { 130 | case 0: 131 | VCK( pa_val>>16 != 0x1 , break; );//not IPv4 132 | pa_val ^= pa_MagicCookie >> 16; 133 | SetPortRes(OPT_MAPADDR_RES,(ushort)(pa_val & 0xffff)); 134 | break; 135 | case 1: 136 | pa_val ^= pa_MagicCookie; 137 | SetIPRes(OPT_MAPADDR_RES,pa_val); 138 | break; 139 | 140 | default: 141 | break; 142 | } 143 | } 144 | else if( pa_attr == 0x0005 ) 145 | { 146 | //CHANGED-ADDRESS 147 | switch( pa_i ) 148 | { 149 | case 0: 150 | VCK( pa_val>>16 != 0x1 , break; );//not IPv4 151 | SetPortRes(OPT_CHANGEADDR_RES,(ushort)(pa_val & 0xffff)); 152 | break; 153 | case 1: 154 | SetIPRes(OPT_CHANGEADDR_RES,pa_val); 155 | break; 156 | 157 | default: 158 | break; 159 | } 160 | 161 | PROMPT(Usual,"CHANGED-ADDRESS attribute recved\n"); 162 | } 163 | else if( pa_attr == 0x0009 ) 164 | { 165 | //ERROR-CODE 166 | TK_EXCEPTION("STUN err return"); 167 | } 168 | } 169 | 170 | static void 171 | StunGetAttributes(void *in_data , uint *out_acc , uint pa_MagicCookie) 172 | { 173 | uint i,cont,AttrLen; 174 | DEF_AND_CAST( pAttr , struct StunAttribute , in_data ); 175 | 176 | AttrLen = ntohs(pAttr->length); 177 | cont = AttrLen / 4; 178 | VCK( (AttrLen % 4 != 0) || 179 | cont > STUN_MAX_VALUES , return; ); 180 | 181 | *out_acc += sizeof(short) + sizeof(short); 182 | for( i = 0 ; i < cont ; i++ ) 183 | { 184 | StunGetValue( ntohs(pAttr->type) , i , ntohl(pAttr->value[i]) ,pa_MagicCookie); 185 | *out_acc += sizeof(int); 186 | } 187 | } 188 | 189 | static uint 190 | StunGetAttrLenFromHead( void *in_data , uint pa_MagicCookie ) 191 | { 192 | DEF_AND_CAST( pHead , struct StunHead , in_data ); 193 | 194 | //VCK( ntohl(pHead->transId1) == pa_MagicCookie , ; ); 195 | VCK( (pHead->transId1) == pa_MagicCookie , ; ); 196 | //I don't know why not use the line commented instead. 197 | 198 | VCK( ntohs(pHead->type) != 0x101 , return 0; ); 199 | 200 | return ntohs( pHead->length ); 201 | } 202 | 203 | BOOL 204 | StunGetResult(void *in_data, uint pa_len , uint pa_MagicCookie , 205 | struct NetAddr *out_MapAddrRes , struct NetAddr *out_ChangeAddrRes) 206 | { 207 | uint now; //offset from head (in bytes) 208 | uint AttrLen = StunGetAttrLenFromHead(in_data , pa_MagicCookie); 209 | 210 | memset(&sta_MapAddrRes , 0 , sizeof(sta_MapAddrRes)); 211 | memset(&sta_ChangeAddrRes , 0 , sizeof(sta_ChangeAddrRes)); 212 | 213 | VCK(AttrLen != pa_len - sizeof(struct StunHead) , return 0; ); 214 | 215 | now = sizeof(struct StunHead); 216 | while( now < pa_len ) 217 | { 218 | StunGetAttributes((char*)in_data + now, &now , pa_MagicCookie); 219 | } 220 | 221 | VCK( sta_MapAddrRes.IPv4 == 0 || 222 | sta_MapAddrRes.port == 0 ,;); 223 | 224 | *out_MapAddrRes = sta_MapAddrRes; 225 | 226 | VCK( sta_ChangeAddrRes.IPv4 == 0 || 227 | sta_ChangeAddrRes.port == 0 ,;); 228 | 229 | *out_ChangeAddrRes = sta_ChangeAddrRes; 230 | 231 | return 1; 232 | } 233 | -------------------------------------------------------------------------------- /stun.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | #define STUN_DEFAULT_PORT 3478 15 | #define STUN_MAX_VALUES 20 16 | 17 | #define STUN_CHANGE_BOTH_IP_PORT 0x01 18 | #define STUN_CHANGE_IP 0x02 19 | #define STUN_CHANGE_PORT 0x03 20 | 21 | struct StunHead 22 | { 23 | ushort type; 24 | ushort length; 25 | uint transId1;//MagicCookie 26 | uint transId2; 27 | uint transId3; 28 | uint transId4; 29 | }; 30 | 31 | struct StunAttribute 32 | { 33 | ushort type; 34 | ushort length; 35 | uint value[STUN_MAX_VALUES]; 36 | }; 37 | 38 | struct ChangeRequest 39 | { 40 | struct StunHead head; 41 | ushort type; 42 | ushort length; 43 | uint value; 44 | }; 45 | 46 | int 47 | StunFormulateRequest(struct StunHead*); 48 | 49 | int 50 | StunFormulateChangeRequest(struct ChangeRequest* , uchar); 51 | 52 | BOOL 53 | StunGetResult(void *, uint , uint , struct NetAddr* , struct NetAddr *); 54 | -------------------------------------------------------------------------------- /sysi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | #include 15 | #include "tknet.h" 16 | 17 | uint g_allocs = 0; 18 | 19 | void* 20 | _tkmalloc( uint pa_len ) 21 | { 22 | g_allocs ++; 23 | return malloc( pa_len ); 24 | } 25 | 26 | void 27 | _tkfree( void* pa_mem ) 28 | { 29 | g_allocs --; 30 | free( pa_mem ); 31 | } 32 | 33 | #if defined( __GNUC__ ) && defined( __linux__ ) 34 | #include 35 | #include 36 | 37 | void 38 | tkInitRandom() 39 | { 40 | unsigned int ticks; 41 | struct timeval tv; 42 | gettimeofday(&tv,NULL); 43 | ticks = tv.tv_sec + tv.tv_usec; 44 | 45 | srand(ticks); 46 | } 47 | 48 | #endif 49 | 50 | #ifdef _MSC_VER 51 | #include 52 | 53 | void 54 | tkInitRandom() 55 | { 56 | srand((unsigned int)time(NULL)); 57 | } 58 | 59 | #endif 60 | 61 | uint 62 | tkGetRandom() 63 | { 64 | return rand(); 65 | } 66 | 67 | #include 68 | 69 | static FILE *sta_pLogFile[ LOG_FILES ]; 70 | static BOOL cst_ifEnableLogFile[ LOG_FILES ]; 71 | 72 | #define LOG_FOPEN( _num , _name , _mode ) \ 73 | cst_ifEnableLogFile[ _num ] = 1; \ 74 | sta_pLogFile[ _num ] = fopen( _name , _mode ); \ 75 | res = res && (uintptr_t)sta_pLogFile[ _num ] 76 | 77 | #include 78 | 79 | int 80 | tkLogInit() 81 | { 82 | uintptr_t res = 1; 83 | LOG_FOPEN( 0 , "tknet.exp" , "w" ); 84 | LOG_FOPEN( 1 , "tknet.log" , "a" ); 85 | return res; 86 | } 87 | 88 | void 89 | tkLog( uint pa_LogNum , const char* pa_log ) 90 | { 91 | if( pa_LogNum < LOG_FILES && cst_ifEnableLogFile[pa_LogNum] ) 92 | { 93 | fwrite( pa_log , 1 , strlen( pa_log ) , sta_pLogFile[pa_LogNum] ); 94 | fflush( sta_pLogFile[pa_LogNum] ); 95 | } 96 | } 97 | 98 | void 99 | tkLogLenDat(uint pa_LogNum , const char* pa_dat , uint pa_len ) 100 | { 101 | if( pa_LogNum < LOG_FILES && cst_ifEnableLogFile[pa_LogNum] ) 102 | { 103 | fwrite( pa_dat , 1 , pa_len , sta_pLogFile[pa_LogNum] ); 104 | fflush( sta_pLogFile[pa_LogNum] ); 105 | } 106 | } 107 | 108 | 109 | void 110 | tkLogClose() 111 | { 112 | uint i; 113 | for( i = 0 ; i < LOG_FILES ; i++ ) 114 | { 115 | if( cst_ifEnableLogFile[i] ) 116 | fclose( sta_pLogFile[i] ); 117 | } 118 | } 119 | 120 | #include 121 | void 122 | tkFormatStr(char* pa_pDest, const char* pa_pFormat , ... ) 123 | { 124 | va_list args; 125 | va_start(args , pa_pFormat); 126 | vsprintf(pa_pDest,pa_pFormat,args); 127 | va_end(args); 128 | } 129 | 130 | #if defined( __GNUC__ ) && defined( __linux__ ) 131 | 132 | #include 133 | 134 | static struct timeval 135 | sta_tim; 136 | 137 | long 138 | tkMilliseconds() 139 | { 140 | gettimeofday(&sta_tim, NULL); 141 | 142 | return sta_tim.tv_sec * 1000 + sta_tim.tv_sec / 1000; 143 | } 144 | 145 | void 146 | tkMsSleep( unsigned long pa_ms ) 147 | { 148 | usleep( pa_ms * 1000); 149 | } 150 | 151 | #elif defined(_MSC_VER) 152 | 153 | long 154 | tkMilliseconds() 155 | { 156 | return clock(); 157 | } 158 | 159 | void 160 | tkMsSleep( unsigned long pa_ms ) 161 | { 162 | Sleep( pa_ms ); 163 | } 164 | 165 | #endif 166 | 167 | #if defined( __GNUC__ ) && defined( __linux__ ) 168 | 169 | void 170 | tkBeginThread(void* (*pa_thread)(void*) ,void *pa_else ) 171 | { 172 | pthread_t id; 173 | pthread_create( &id , NULL , pa_thread , pa_else ); 174 | } 175 | 176 | #elif defined(_MSC_VER) 177 | 178 | void 179 | tkBeginThread(void* (*pa_thread)(void*) ,void *pa_else ) 180 | { 181 | CreateThread(0,0,(LPTHREAD_START_ROUTINE)pa_thread , pa_else ,0,0); 182 | } 183 | 184 | #endif 185 | 186 | void 187 | StrTraceFormat( char *in_str ) 188 | { 189 | int i; 190 | char *buff = (char*)malloc( strlen(in_str) + 1 ); 191 | strcpy( buff , in_str ); 192 | 193 | for(i=0;buff[i]!='\0';i++) 194 | { 195 | if(buff[i] == '\r') 196 | { 197 | buff[i] = 'R'; 198 | } 199 | else if(buff[i] == '\n') 200 | { 201 | buff[i] = 'N'; 202 | } 203 | else if(buff[i] == ' ') 204 | { 205 | buff[i] = '_'; 206 | } 207 | } 208 | 209 | PROMPT(Usual,"%s",buff); 210 | free(buff); 211 | } 212 | 213 | struct pipe *g_pImportantPrompt = NULL; 214 | struct pipe *g_pUsualPrompt = NULL; 215 | struct pipe *g_pDebugPrompt = NULL; 216 | const char g_ImportantPromptName[] = "ImportantPrompt"; 217 | const char g_UsualPromptName[] = "UsualPrompt"; 218 | const char g_DebugPromptName[] = "DebugPrompt"; 219 | 220 | void 221 | Prompt(struct pipe *pa_pPipe,const char *pa_pPipeName, 222 | char* pa_pFormat, ...) 223 | { 224 | static char buff[PROMT_BUFFERSIZE]; 225 | va_list args; 226 | va_start(args, pa_pFormat); 227 | vsnprintf(buff,PROMT_BUFFERSIZE,pa_pFormat,args); 228 | va_end(args); 229 | 230 | if(pa_pPipe == NULL) 231 | { 232 | pa_pPipe = PipeMap((char*)pa_pPipeName); 233 | } 234 | 235 | PipeFlow(pa_pPipe,buff,strlen(buff),NULL); 236 | //Do not flow '\0' in string pipe. 237 | } 238 | -------------------------------------------------------------------------------- /sysi.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | extern unsigned int g_allocs; 20 | 21 | void* 22 | _tkmalloc( unsigned int ); 23 | 24 | void 25 | _tkfree( void* ); 26 | 27 | #define tkmalloc( _type_tage ) \ 28 | ( _type_tage *)_tkmalloc( sizeof ( _type_tage ) ) 29 | 30 | #define tkfree( _mem ) \ 31 | _tkfree( _mem ); \ 32 | _mem = NULL 33 | 34 | void 35 | tkInitRandom(); 36 | 37 | unsigned int 38 | tkGetRandom(); 39 | 40 | #define LOG_FILES 2 41 | 42 | int 43 | tkLogInit(); 44 | 45 | void 46 | tkLog( unsigned int , const char* ); 47 | 48 | void 49 | tkLogLenDat(unsigned int , const char* , unsigned int ); 50 | //this log function doesn't expect any '\0' in data to write. 51 | 52 | void 53 | tkLogClose(); 54 | 55 | void 56 | tkFormatStr(char* , const char* , ... ); 57 | 58 | long 59 | tkMilliseconds(); 60 | 61 | void 62 | tkMsSleep( unsigned long ); 63 | 64 | void 65 | tkBeginThread(void* (*)(void*) ,void * ); 66 | 67 | #define TK_THREAD( _thread_name ) void* _thread_name (void *pa_else) 68 | 69 | #if defined( __GNUC__ ) && defined( __linux__ ) 70 | 71 | #include 72 | 73 | #define tkMutex pthread_mutex_t 74 | #define MutexInit( _mutex ) pthread_mutex_init( _mutex, NULL) 75 | #define MutexLock( _mutex ) pthread_mutex_lock( _mutex) 76 | #define MutexUnlock( _mutex ) pthread_mutex_unlock( _mutex) 77 | #define MutexDelete( _mutex ) pthread_mutex_destroy( _mutex) 78 | 79 | #elif defined(_MSC_VER) 80 | 81 | #define tkMutex CRITICAL_SECTION 82 | #define MutexInit( _mutex ) InitializeCriticalSection( _mutex) 83 | #define MutexLock( _mutex ) EnterCriticalSection( _mutex) 84 | #define MutexUnlock( _mutex ) LeaveCriticalSection( _mutex) 85 | #define MutexDelete( _mutex ) DeleteCriticalSection( _mutex) 86 | 87 | #endif 88 | 89 | void 90 | StrTraceFormat( char* ); 91 | 92 | extern struct pipe *g_pImportantPrompt; 93 | extern struct pipe *g_pUsualPrompt; 94 | extern struct pipe *g_pDebugPrompt; 95 | extern const char g_ImportantPromptName[]; 96 | extern const char g_UsualPromptName[]; 97 | extern const char g_DebugPromptName[]; 98 | 99 | #define PROMPT( _pipe , ... ) \ 100 | Prompt( g_p ## _pipe ## Prompt , g_ ## _pipe ## PromptName , __VA_ARGS__) 101 | 102 | #define PROMT_BUFFERSIZE 1024 103 | 104 | void 105 | Prompt(struct pipe *,const char *,char* , ...); 106 | -------------------------------------------------------------------------------- /test/bin/dir0/tknet.info: -------------------------------------------------------------------------------- 1 | Config 127.0.0.1 8912 LAN dir0 StdinToCmd 2 | -------------------------------------------------------------------------------- /test/bin/dir1/tknet.info: -------------------------------------------------------------------------------- 1 | Config 127.0.0.1 8921 LAN dir1 dir3 StdinToCmd 2 | BridgePeer 127.0.0.1 8912 3 | -------------------------------------------------------------------------------- /test/bin/dir2/tknet.info: -------------------------------------------------------------------------------- 1 | Config 127.0.0.1 8922 LAN dir2 StdinToCmd 2 | BridgePeer 127.0.0.1 8912 3 | -------------------------------------------------------------------------------- /test/bin/dir3/tknet.info: -------------------------------------------------------------------------------- 1 | Config 127.0.0.1 8923 LAN dir3 dir1 StdinToCmd 2 | BridgePeer 127.0.0.1 8912 3 | -------------------------------------------------------------------------------- /test/demo.c: -------------------------------------------------------------------------------- 1 | #include "../tknet.h" 2 | 3 | int main(int n,char **args) 4 | { 5 | return tkNetMain(n,args); 6 | } 7 | 8 | void 9 | ON_CONNECT() 10 | { 11 | printf("ON_CONNECT() called.\n"); 12 | } 13 | -------------------------------------------------------------------------------- /test/demos/bkgd-demo.c: -------------------------------------------------------------------------------- 1 | #include "headers.h" 2 | 3 | BOOL g_MainLoopFlag = 1; 4 | uchar g_NATtype = NAT_T_UNKNOWN; 5 | 6 | void tkNetInit() 7 | { 8 | tkInitRandom(); 9 | tkLogInit(); 10 | SockInit(); 11 | } 12 | 13 | void tkNetUninit() 14 | { 15 | SockDestory(); 16 | tkLogClose(); 17 | printf("unfree memory:%d \n",g_allocs); 18 | } 19 | 20 | int main() 21 | { 22 | struct KeyInfoCache KeyInfoCache; 23 | struct ProcessingList ProcList; 24 | struct BackGroundArgs BkgdArgs; 25 | tkNetInit(); 26 | 27 | ProcessingListCons( &ProcList ); 28 | 29 | KeyInfoCacheCons(&KeyInfoCache); 30 | KeyInfoReadFile(&KeyInfoCache,"tknet.info"); 31 | 32 | while(!KeyInfoTry(&KeyInfoCache,KEY_INFO_TYPE_STUNSERVER)) 33 | { 34 | if(!KeyInfoTry(&KeyInfoCache,KEY_INFO_TYPE_MAILSERVER)) 35 | { 36 | printf("No way :( \n"); 37 | goto exit; 38 | } 39 | } 40 | printf("NAT: %d\n",g_NATtype); 41 | 42 | /*while(!KeyInfoTry(&KeyInfoCache,KEY_INFO_TYPE_BRIDGEPEER)) 43 | { 44 | if(!KeyInfoTry(&KeyInfoCache,KEY_INFO_TYPE_MAILSERVER)) 45 | { 46 | printf("No way :( \n"); 47 | goto exit; 48 | } 49 | }*/ 50 | 51 | MutexInit(&g_BkgdMutex); 52 | 53 | BkgdArgs.pInfoCache = &KeyInfoCache; 54 | BkgdArgs.pProcList = &ProcList; 55 | tkBeginThread( &BackGround , &BkgdArgs ); 56 | 57 | while( g_MainLoopFlag ) 58 | { 59 | MutexLock(&g_BkgdMutex); 60 | DoProcessing( &ProcList ); 61 | MutexUnlock(&g_BkgdMutex); 62 | 63 | tkMsSleep(100); 64 | } 65 | 66 | exit: 67 | 68 | KeyInfoUpdate( &KeyInfoCache ); 69 | KeyInfoWriteFile(&KeyInfoCache,"baba.info"); 70 | KeyInfoFree(&KeyInfoCache); 71 | MutexDelete(&g_BkgdMutex); 72 | tkNetUninit(); 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /test/demos/keyinfo-demo.c: -------------------------------------------------------------------------------- 1 | #include "headers.h" 2 | 3 | BOOL g_MainLoopFlag = 1; 4 | uchar g_NATtype = NAT_T_UNKNOWN; 5 | 6 | void tkNetInit() 7 | { 8 | tkInitRandom(); 9 | tkLogInit(); 10 | SockInit(); 11 | } 12 | 13 | void tkNetUninit() 14 | { 15 | SockDestory(); 16 | tkLogClose(); 17 | printf("unfree memory:%d \n",g_allocs); 18 | } 19 | 20 | int main() 21 | { 22 | struct KeyInfoCache KeyInfoCache; 23 | BOOL res; 24 | tkNetInit(); 25 | 26 | KeyInfoCacheCons(&KeyInfoCache); 27 | KeyInfoReadFile(&KeyInfoCache,"tknet.info"); 28 | 29 | while(!KeyInfoTry(&KeyInfoCache,KEY_INFO_TYPE_STUNSERVER)) 30 | { 31 | if(!KeyInfoTry(&KeyInfoCache,KEY_INFO_TYPE_MAILSERVER)) 32 | { 33 | printf("No way :( \n"); 34 | goto exit; 35 | } 36 | } 37 | 38 | printf("NAT: %d\n",g_NATtype); 39 | exit: 40 | 41 | KeyInfoTrace(&KeyInfoCache); 42 | KeyInfoUpdate( &KeyInfoCache ); 43 | KeyInfoTrace(&KeyInfoCache); 44 | KeyInfoWriteFile(&KeyInfoCache,"baba.info"); 45 | KeyInfoFree(&KeyInfoCache); 46 | 47 | tkNetUninit(); 48 | 49 | return 0; 50 | } 51 | -------------------------------------------------------------------------------- /test/demos/list-demo.c: -------------------------------------------------------------------------------- 1 | #include "headers.h" 2 | #include 3 | #include 4 | 5 | struct I 6 | { 7 | int i; 8 | struct ListNode sajfkjh; 9 | }; 10 | 11 | DEF_STRUCT_CONSTRUCTOR( I , 12 | out_cons-> i = rand() % 12; 13 | ListNodeCons( &( out_cons->sajfkjh ) ); 14 | ) 15 | 16 | BOOL 17 | compare(struct Iterator* compared0 , struct Iterator* compared1 , void* pa_else) 18 | { 19 | struct I* p0 = NULL; 20 | struct I* p1 = NULL; 21 | 22 | p0 = GET_STRUCT_ADDR_FROM_IT( compared0 , struct I , sajfkjh ); 23 | p1 = GET_STRUCT_ADDR_FROM_IT( compared1 , struct I , sajfkjh ); 24 | 25 | return p0->i < p1->i ; 26 | } 27 | 28 | BOOL 29 | LIST_ITERATION_CALLBACK_FUNCTION(trace) 30 | { 31 | struct I* p = GET_STRUCT_ADDR_FROM_IT( pa_pINow , struct I , sajfkjh ); 32 | 33 | printf("%d->",p->i); 34 | 35 | return pa_pINow->now == pa_pIHead->last; 36 | } 37 | 38 | static 39 | DEF_FREE_LIST_ELEMENT_CALLBACK_FUNCTION( FreeI , struct I, sajfkjh , printf("dele %d ,",pNow->i); ) 40 | 41 | static 42 | DEF_FREE_LIST_ELEMENT_SAFE_FUNCTION( FreeIs , struct I, sajfkjh , printf("dele %d :\n",pNow->i); 43 | ForEach(pa_pIHead,&trace,NULL); 44 | printf(" that's all. \n"); 45 | ) 46 | 47 | int main() 48 | { 49 | int seed,res,i = 0; 50 | struct Iterator i_list = GetIterator(NULL); 51 | struct I* add; 52 | struct SortingInsertPa sip; 53 | sip.si_cbk = &compare; 54 | 55 | printf("random seed \n"); 56 | res = scanf("%d", &seed); 57 | srand(seed + 12745); 58 | 59 | for( i = 0 ; i < 9 ; i++ ) 60 | { 61 | add = (struct I*)malloc( sizeof (struct I) ); 62 | ICons(add); 63 | AddOneToListHead( &i_list, &(add->sajfkjh) ); 64 | printf("add %d ,",add->i); 65 | } 66 | printf(" that's all. \n"); 67 | 68 | ForEach(&i_list,&trace,NULL); 69 | printf(" that's all. \n"); 70 | 71 | ReverseList(&i_list); 72 | ForEach(&i_list,&trace,NULL); 73 | printf(" that's all. \n"); 74 | 75 | SortList( &i_list , &sip); 76 | ForEach(&i_list,&trace,NULL); 77 | printf(" that's all. \n"); 78 | 79 | //ForEach(&i_list,&FreeI,NULL); 80 | ForEach(&i_list,&FreeIs,NULL); 81 | printf(" that's all... \n"); 82 | 83 | return 0; 84 | } 85 | -------------------------------------------------------------------------------- /test/demos/most-simple-UDP-demo.c: -------------------------------------------------------------------------------- 1 | #include "sysi.h" 2 | #include "comdef.h" 3 | #include "sock.h" 4 | 5 | int 6 | main(int argc, char **argv) 7 | { 8 | struct Sock client; 9 | char buff[128]; 10 | SockInit(); 11 | 12 | printf("port: %d -> %d \n", atoi(argv[1]) , atoi(argv[2]) ); 13 | 14 | SockOpen( &client , UDP , atoi(argv[1]) ); 15 | 16 | SockLocateTa( &client , GetIPVal("127.0.0.1") , atoi(argv[2]) ); 17 | 18 | SockSetNonblock( &client ); 19 | 20 | while(1) 21 | { 22 | if(SockRead( &client )) 23 | { 24 | printf("%s \n",client.RecvBuff); 25 | } 26 | 27 | scanf("%s",buff); 28 | SockWrite( &client , StrBys(buff) ); 29 | 30 | sleep(1); 31 | } 32 | 33 | SockClose( &client ); 34 | SockDestory(); 35 | 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /test/demos/nattype-demo.c: -------------------------------------------------------------------------------- 1 | #include "headers.h" 2 | 3 | void tkNetInit(); 4 | void tkNetUninit(); 5 | BOOL g_flag = 1; 6 | void Notify(struct Process *pa_) 7 | { 8 | struct STUNProc *pProc = GET_STRUCT_ADDR(pa_ , struct STUNProc , proc); 9 | 10 | switch( pProc->NatTypeRes ) 11 | { 12 | case NAT_T_FULL_CONE: 13 | printf("NAT type: full cone. \n"); 14 | break; 15 | case NAT_T_RESTRICTED: 16 | printf("NAT type: restricted cone. \n"); 17 | break; 18 | case NAT_T_PORT_RESTRICTED: 19 | printf("NAT type: port restricted cone. \n"); 20 | break; 21 | case NAT_T_SYMMETRIC: 22 | printf("NAT type: symmetric \n"); 23 | break; 24 | default: 25 | printf("NAT type: unknown. \n"); 26 | } 27 | 28 | ProcessTraceSteps(pa_); 29 | g_flag = 0; 30 | } 31 | 32 | int main() 33 | { 34 | struct ProcessingList ProcList; 35 | struct Sock StunSock; 36 | struct STUNProc StunProc; 37 | char buff[32]; 38 | tkNetInit(); 39 | 40 | ProcessingListCons( &ProcList ); 41 | SockOpen( &StunSock , UDP , 8821 ); 42 | SockSetNonblock( &StunSock ); 43 | 44 | MakeProtoStunProc(&StunProc ,&StunSock , "132.177.123.13",STUN_DEFAULT_PORT); 45 | StunProc.proc.NotifyCallbk = &Notify; 46 | 47 | ProcessStart( &StunProc.proc , &ProcList ); 48 | 49 | while( g_flag ) 50 | { 51 | DoProcessing( &ProcList ); 52 | usleep( 100 * 1000); 53 | } 54 | 55 | ProcessFree(&StunProc.proc); 56 | tkNetUninit(); 57 | return 0; 58 | } 59 | 60 | void tkNetInit() 61 | { 62 | tkInitRandom(); 63 | tkLogInit(); 64 | SockInit(); 65 | } 66 | 67 | void tkNetUninit() 68 | { 69 | SockDestory(); 70 | tkLogClose(); 71 | printf("unfree memory:%d \n",g_allocs); 72 | } 73 | -------------------------------------------------------------------------------- /test/demos/netproc-demo.c: -------------------------------------------------------------------------------- 1 | #include "headers.h" 2 | 3 | void Notify( struct Process *pa_pProc) 4 | { 5 | printf(" proc end notify \n"); 6 | } 7 | 8 | STEP( First ) 9 | { 10 | if( pa_state == PS_STATE_FIRST_TIME ) 11 | { 12 | printf("first step begin:"); 13 | ProcessTraceSteps( pa_pProc ); 14 | } 15 | else if( pa_state == PS_STATE_OVERTIME ) 16 | { 17 | printf("first step retry:"); 18 | ProcessTraceSteps( pa_pProc ); 19 | 20 | if( tkGetRandom() % 10 == 1 ) 21 | { 22 | printf(" random abort! \n"); 23 | return PS_CALLBK_RET_ABORT; 24 | } 25 | } 26 | else if( pa_state == PS_STATE_LAST_TIME ) 27 | { 28 | printf("first step over:"); 29 | ProcessTraceSteps( pa_pProc ); 30 | } 31 | 32 | return PS_CALLBK_RET_GO_ON; 33 | } 34 | 35 | STEP( Second ) 36 | { 37 | uint ran = 0; 38 | if( pa_state == PS_STATE_OVERTIME ) 39 | { 40 | printf("second step first over-time: \n"); 41 | ProcessTraceSteps( pa_pProc ); 42 | 43 | ran = tkGetRandom()%10; 44 | printf("random=%d ,", ran); 45 | if( ran < 3) 46 | { 47 | printf("Go back to step 0\n"); 48 | return FlagNum(0); 49 | } 50 | else if( ran < 7 ) 51 | { 52 | printf("Go to step 1\n"); 53 | return FlagNum(1); 54 | } 55 | else 56 | { 57 | printf("Go to step 2\n"); 58 | return FlagNum(2); 59 | } 60 | } 61 | 62 | return PS_CALLBK_RET_GO_ON; 63 | } 64 | 65 | STEP( Third ) 66 | { 67 | if( pa_state == PS_STATE_FIRST_TIME ) 68 | { 69 | printf("Third step first time: "); 70 | ProcessTraceSteps( pa_pProc ); 71 | } 72 | else if( pa_state == PS_STATE_OVERTIME ) 73 | { 74 | printf("Third step retry: "); 75 | ProcessTraceSteps( pa_pProc ); 76 | } 77 | 78 | return PS_CALLBK_RET_GO_ON; 79 | } 80 | 81 | STEP( circle ) 82 | { 83 | if( pa_state == PS_STATE_FIRST_TIME ) 84 | { 85 | printf("circle step: \n"); 86 | ProcessTraceSteps( pa_pProc ); 87 | } 88 | else if( pa_state == PS_STATE_OVERTIME ) 89 | { 90 | return PS_CALLBK_RET_REDO; 91 | } 92 | 93 | return PS_CALLBK_RET_GO_ON; 94 | } 95 | 96 | int main() 97 | { 98 | struct ProcessingList ProcList; 99 | struct Process ProcTemplate; 100 | struct Process ProcTemplate2; 101 | struct Process Proc[6]; 102 | int i; 103 | 104 | tkInitRandom(); 105 | tkLogInit(); 106 | ProcessingListCons( &ProcList ); 107 | 108 | ProcessCons( &ProcTemplate ); 109 | ProcTemplate.NotifyCallbk = &Notify; 110 | PROCESS_ADD_STEP( &ProcTemplate , First , 1000 , 8 ); 111 | PROCESS_ADD_STEP( &ProcTemplate , Second , 5000 , 3 ); 112 | PROCESS_ADD_STEP( &ProcTemplate , Third , 2000 , 5 ); 113 | 114 | ProcessCons( &ProcTemplate2 ); 115 | PROCESS_ADD_STEP( &ProcTemplate2 , circle , 1500 , 3 ); 116 | 117 | for(i=0;i<6;i++) 118 | { 119 | ProcessConsAndSetSteps( Proc + i , &ProcTemplate ); 120 | Proc[i].NotifyCallbk = &Notify; 121 | ProcessStart( Proc + i , &ProcList ); 122 | } 123 | 124 | ProcessStart( &ProcTemplate , &ProcList ); 125 | ProcessStart( &ProcTemplate2 , &ProcList ); 126 | 127 | while(1) 128 | { 129 | DoProcessing( &ProcList ); 130 | sleep(1); 131 | } 132 | 133 | tkLogClose(); 134 | 135 | return 0; 136 | } 137 | -------------------------------------------------------------------------------- /test/demos/peerdata-demo.c: -------------------------------------------------------------------------------- 1 | #include "headers.h" 2 | 3 | void tkNetInit() 4 | { 5 | tkInitRandom(); 6 | tkLogInit(); 7 | SockInit(); 8 | } 9 | 10 | void tkNetUninit() 11 | { 12 | SockDestory(); 13 | tkLogClose(); 14 | printf("unfree memory:%d \n",g_allocs); 15 | } 16 | 17 | int main() 18 | { 19 | struct PeerData PeerDataRoot,*p; 20 | int i; 21 | char buff[32]; 22 | struct NetAddr addr; 23 | tkNetInit(); 24 | 25 | PeerDataCons(&PeerDataRoot); 26 | PeerDataRoot.tpnd.RanPriority = 0; 27 | PeerDataRoot.addr.port = 0; 28 | PeerDataRoot.addr.IPv4 = 0; 29 | 30 | for(i=0;i<9;i++) 31 | { 32 | p = tkmalloc(struct PeerData); 33 | PeerDataCons(p); 34 | p->addr.port = (ushort)tkGetRandom(); 35 | p->addr.IPv4 = tkGetRandom(); 36 | 37 | GetAddrText(&addr,buff); 38 | if(PeerDataFind(&PeerDataRoot,&addr)) 39 | { 40 | printf("find\n"); 41 | } 42 | else 43 | { 44 | printf("NOT find %s\n",buff); 45 | } 46 | 47 | p->NATType = NAT_T_UNKNOWN; 48 | PeerDataInsert(p,&PeerDataRoot); 49 | addr = p->addr; 50 | } 51 | 52 | PeerDataTrace(&PeerDataRoot); 53 | PeerDataDestroy(&PeerDataRoot); 54 | 55 | tkNetUninit(); 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /test/demos/pipe-demo.c: -------------------------------------------------------------------------------- 1 | #include "tknet.h" 2 | 3 | int main() 4 | { 5 | char buff[256],*pArg0,*pArg1; 6 | struct pipe *pPipe0,*pPipe1; 7 | uint i; 8 | char get_c; 9 | 10 | PipeModuleInit(); 11 | 12 | while(1) 13 | { 14 | fgets(buff,255,stdin); 15 | buff[strlen(buff)-1] = '\0'; 16 | 17 | pArg0 = strtok(buff," "); 18 | pArg1 = strtok(NULL," "); 19 | 20 | if(pArg0 == NULL) 21 | continue; 22 | 23 | if(pArg1) 24 | { 25 | if(strcmp(pArg0,"dele") == 0) 26 | { 27 | pPipe1 = PipeFindByName(pArg1); 28 | 29 | if(pPipe1) 30 | { 31 | PipeDele(pPipe1); 32 | } 33 | else 34 | { 35 | printf("can't find %s.\n",pArg1); 36 | } 37 | } 38 | else 39 | { 40 | pPipe0 = PipeMap(pArg0,(char**)&buff,&i,PIPE_WRITE); 41 | pPipe1 = PipeFindByName(pArg1); 42 | 43 | if(pPipe1) 44 | { 45 | printf("only? y/n \n"); 46 | get_c = getchar(); 47 | if(get_c=='y') 48 | PipeDirectOnlyTo(pPipe0,pPipe1); 49 | else 50 | PipeDirectTo(pPipe0,pPipe1); 51 | 52 | printf("\n"); 53 | } 54 | else 55 | { 56 | printf("can't find %s.\n",pArg1); 57 | } 58 | } 59 | } 60 | else if(strcmp(pArg0,"exit") == 0) 61 | { 62 | break; 63 | } 64 | else 65 | { 66 | PipeMap(pArg0,(char**)&buff,&i,PIPE_READ); 67 | } 68 | 69 | PipeTablePrint(); 70 | } 71 | 72 | PipeModuleUninit(); 73 | printf("unfree memory:%d \n",g_allocs); 74 | return 0; 75 | } 76 | -------------------------------------------------------------------------------- /test/demos/popmail-demo.c: -------------------------------------------------------------------------------- 1 | #include "headers.h" 2 | BOOL flag = 1; 3 | 4 | void Notify( struct Process *pa_pProc) 5 | { 6 | printf(" proc end notify \n"); 7 | flag = 0; 8 | ProcessTraceSteps( pa_pProc ); 9 | } 10 | 11 | void tkNetInit(); 12 | void tkNetUninit(); 13 | 14 | int main() 15 | { 16 | struct ProcessingList ProcList; 17 | struct Sock pop3sock; 18 | struct POP3Proc NetProtoPOP3; 19 | 20 | tkNetInit(); 21 | 22 | ProcessingListCons( &ProcList ); 23 | SockOpen( &pop3sock , TCP , 0); 24 | 25 | MakeProtoPOP3Proc( &NetProtoPOP3 , "220.181.12.101" ,110,0,"li28jhyxy76223","g131517"); 26 | NetProtoPOP3.proc.NotifyCallbk = &Notify; 27 | NetProtoPOP3.pSock = &pop3sock; 28 | 29 | ProcessStart( &NetProtoPOP3.proc , &ProcList ); 30 | 31 | while( flag ) 32 | { 33 | DoProcessing( &ProcList ); 34 | usleep( 100 * 1000); 35 | } 36 | 37 | ForEach( &NetProtoPOP3.IMailsHead , &TraceMail , NULL ); 38 | 39 | POP3ProcFree( &NetProtoPOP3 ); 40 | 41 | tkNetUninit(); 42 | return 0; 43 | } 44 | 45 | void tkNetInit() 46 | { 47 | tkInitRandom(); 48 | tkLogInit(); 49 | SockInit(); 50 | } 51 | 52 | void tkNetUninit() 53 | { 54 | SockDestory(); 55 | tkLogClose(); 56 | printf("unfree memory:%d \n",g_allocs); 57 | } 58 | -------------------------------------------------------------------------------- /test/demos/smtpmail-demo.c: -------------------------------------------------------------------------------- 1 | #include "headers.h" 2 | 3 | void tkNetInit(); 4 | void tkNetUninit(); 5 | BOOL g_flag = 1; 6 | void Notify(struct Process *pa_) 7 | { 8 | ProcessTraceSteps(pa_); 9 | g_flag = 0; 10 | } 11 | 12 | int main() 13 | { 14 | struct ProcessingList ProcList; 15 | struct SMTPProc SmtpProc; 16 | tkNetInit(); 17 | 18 | ProcessingListCons( &ProcList ); 19 | 20 | SMTPProcMake(&SmtpProc ,"113.108.225.10" , 25,0,"li28jhyxy76223","g131517","li28jhyxy76223@163.com","Ok"); 21 | SmtpProc.proc.NotifyCallbk = &Notify; 22 | ProcessStart( &SmtpProc.proc , &ProcList ); 23 | 24 | while( g_flag ) 25 | { 26 | DoProcessing( &ProcList ); 27 | usleep( 100 * 1000); 28 | } 29 | 30 | ProcessFree(&SmtpProc.proc); 31 | tkNetUninit(); 32 | return 0; 33 | } 34 | 35 | void tkNetInit() 36 | { 37 | tkInitRandom(); 38 | tkLogInit(); 39 | SockInit(); 40 | } 41 | 42 | void tkNetUninit() 43 | { 44 | SockDestory(); 45 | tkLogClose(); 46 | printf("unfree memory:%d \n",g_allocs); 47 | } 48 | -------------------------------------------------------------------------------- /test/demos/sock-demo.c: -------------------------------------------------------------------------------- 1 | #include "headers.h" 2 | #include 3 | 4 | //-----------------TCP SSL demo------------------------ 5 | int 6 | main() 7 | { 8 | struct Sock client; 9 | ushort port; 10 | char buff[32]; 11 | int res = 0; 12 | 13 | buff[0]='a'; 14 | buff[1]='\0'; 15 | SockInit(); 16 | tkLogInit(); 17 | 18 | SockOpen( &client , TCP , 0 ); 19 | // 20 | 21 | GetIPTextAndPort(&client.AddrMe,&port,buff); 22 | printf("my addr: %s/%d \n",buff,port); 23 | 24 | if (!SockLocateTa( &client , GetIPVal("123.125.50.23") , 995 )) 25 | { 26 | printf("last error: %d \n", SockGetLastErr() ); 27 | return 0; 28 | } 29 | 30 | GetIPTextAndPort(&client.AddrTa,&port,buff); 31 | printf("ta addr: %s/%d \n",buff,port); 32 | 33 | SockSSLConnect( &client ); 34 | 35 | res = SockRead( &client ); 36 | GetIPTextAndPort(&client.AddrRecvfrom,&port,buff); 37 | printf("read:%s ,from %s/%d res=%d \n",client.RecvBuff,buff,port,res); 38 | 39 | SockWrite( &client , StrBys("USER clock126\r\n") ); 40 | 41 | res = SockRead( &client ); 42 | GetIPTextAndPort(&client.AddrRecvfrom,&port,buff); 43 | printf("read:%s ,from %s/%d res=%d \n",client.RecvBuff,buff,port,res); 44 | 45 | SockClose( &client ); 46 | SockDestory(); 47 | 48 | return 0; 49 | 50 | } 51 | 52 | /* 53 | //-----------------TCP demo----------------------------- 54 | int 55 | main() 56 | { 57 | struct Sock client; 58 | ushort port; 59 | char buff[32]; 60 | int res = 0; 61 | 62 | SockInit(); 63 | tkLogInit(); 64 | 65 | SockOpen( &client , TCP , 8812 ); 66 | 67 | GetIPTextAndPort(&client.AddrMe,&port,buff); 68 | printf("my addr: %s/%d \n",buff,port); 69 | 70 | if (!SockLocateTa( &client , GetIPVal("123.125.50.23") , 110 )) 71 | //126 mail server 72 | { 73 | printf("last error: %d \n", SockGetLastErr() ); 74 | return 0; 75 | } 76 | 77 | GetIPTextAndPort(&client.AddrTa,&port,buff); 78 | printf("ta addr: %s/%d \n",buff,port); 79 | 80 | res = SockRead( &client ); 81 | GetIPTextAndPort(&client.AddrRecvfrom,&port,buff); 82 | printf("read:%s ,from %s/%d res=%d \n",client.RecvBuff,buff,port,res); 83 | 84 | SockWrite( &client , StrBys("USER clock126\r\n") ); 85 | 86 | res = SockRead( &client ); 87 | GetIPTextAndPort(&client.AddrRecvfrom,&port,buff); 88 | printf("read:%s ,from %s/%d res=%d \n",client.RecvBuff,buff,port,res); 89 | 90 | SockClose( &client ); 91 | SockDestory(); 92 | 93 | return 0; 94 | } 95 | 96 | //-----------------TCP POP3 demo------------------------ 97 | int main() 98 | { 99 | struct Sock s; 100 | 101 | tkLogInit(); 102 | SockInit(); 103 | 104 | SockOpen( &s , TCP , 8812 ); 105 | SockLocateTa( &s , GetIPVal("220.181.15.128") ,110 ); 106 | 107 | SockSetNonblock( &s ); 108 | 109 | while(!SockRead(&s)); 110 | printf("\n read:%s \n", s.RecvBuff); 111 | SockWrite( &s , StrBys("USER clock126\r\n") ); 112 | 113 | while(!SockRead(&s)); 114 | printf("\n read:%s \n", s.RecvBuff); 115 | SockWrite( &s , StrBys("PASS bula..bula\r\n") ); 116 | while(!SockRead(&s)); 117 | printf("\n read:%s \n", s.RecvBuff); 118 | 119 | SockWrite( &s , StrBys("LIST\r\n") ); 120 | while(!SockRead(&s)); 121 | printf("\n read:%s \n", s.RecvBuff); 122 | 123 | SockWrite( &s , StrBys("RETR 278\r\n") ); 124 | while(!SockRead(&s)); 125 | printf("\n read:%s \n", s.RecvBuff); 126 | 127 | while(!SockRead(&s)); 128 | printf("\n read:%s \n", s.RecvBuff); 129 | 130 | SockDestory(); 131 | tkLogClose(); 132 | return 0; 133 | } 134 | */ 135 | -------------------------------------------------------------------------------- /test/demos/treap-demo.c: -------------------------------------------------------------------------------- 1 | #include "headers.h" 2 | #include 3 | 4 | struct Test 5 | { 6 | uint i; 7 | uint level; 8 | struct Treap trp; 9 | }; 10 | 11 | BOOL Test_compare(struct BinTreeNode* pa_bigger, 12 | struct BinTreeNode* pa_than, void* pa_else) 13 | { 14 | struct Test* p0 = GET_STRUCT_ADDR( pa_bigger , struct Test , trp.btnd ); 15 | struct Test* p1 = GET_STRUCT_ADDR( pa_than , struct Test , trp.btnd ); 16 | return p0->i > p1->i; 17 | } 18 | 19 | BOOL Test_eq(struct BinTreeNode* pa_bigger, 20 | struct BinTreeNode* pa_than, void* pa_else) 21 | { 22 | struct Test* p0 = GET_STRUCT_ADDR( pa_bigger , struct Test , trp.btnd ); 23 | struct Test* p1 = GET_STRUCT_ADDR( pa_than , struct Test , trp.btnd ); 24 | return p0->i == p1->i; 25 | } 26 | 27 | BOOL 28 | LIST_ITERATION_CALLBACK_FUNCTION( TraceTreap ) 29 | { 30 | struct Branch* pBranch = 31 | GET_STRUCT_ADDR_FROM_IT( pa_pINow , struct Branch , ln); 32 | 33 | struct Test* p = 34 | GET_STRUCT_ADDR( pBranch->pChild , struct Test , trp.btnd.tnd); 35 | 36 | int i;char c; 37 | struct BinTreeNode *pBinFather; 38 | if(p->level < 32) 39 | { 40 | for(i=0;ilevel;i++) 41 | { 42 | printf(" "); 43 | } 44 | } 45 | 46 | pBinFather = GET_STRUCT_ADDR(p->trp.btnd.tnd.pFather, struct BinTreeNode , tnd); 47 | if(pBinFather->RightChild == &(p->trp.btnd)) 48 | { 49 | c='R'; 50 | } 51 | else if(pBinFather->LeftChild == &(p->trp.btnd)) 52 | { 53 | c='L'; 54 | } 55 | else 56 | { 57 | c='x'; 58 | } 59 | 60 | printf("%d %c(%d) at level%d \n", p->i ,c, p->trp.RanPriority ,p->level ); 61 | 62 | return pa_pINow->now == pa_pIHead->last; 63 | } 64 | 65 | DEF_FREE_TREE_ELEMENT_CALLBACK_FUNCTION( FreeTreap , struct Test , trp.btnd.tnd , printf("dele %d \n", pTreeNow->i); ) 66 | 67 | void SetLevel(struct TreeNode* pa_pTnd , uint pa_level) 68 | { 69 | struct Test *pTest = 70 | GET_STRUCT_ADDR( pa_pTnd , struct Test , trp.btnd.tnd ); 71 | 72 | pTest->level = pa_level; 73 | } 74 | 75 | #define MAX_NUM 9 76 | int main() 77 | { 78 | struct Test root,*pFindTest,ToFind,*p[MAX_NUM]; 79 | struct BinTreeNode *pFind; 80 | uint i; 81 | tkInitRandom(); 82 | 83 | TreapCons(&root.trp); 84 | root.i = 0; 85 | root.trp.RanPriority = 0; 86 | 87 | for(i=0;ilevel = 0; 91 | TreapCons(&(p[i]->trp)); 92 | 93 | while(1) 94 | { 95 | p[i]->i = tkGetRandom() % (MAX_NUM * 5); 96 | ToFind.i = p[i]->i; 97 | pFind = BinTreeFind(&root.trp.btnd,&ToFind.trp.btnd,&Test_compare,&Test_eq,NULL); 98 | if(pFind == NULL) 99 | { 100 | break; 101 | } 102 | } 103 | TreapInsert(&(p[i]->trp) ,&(root.trp) , Test_compare , NULL); 104 | } 105 | 106 | while(1) 107 | { 108 | printf("allocs = %d \n",g_allocs); 109 | 110 | TreeGetNodesLevel(&(root.trp.btnd.tnd),&SetLevel); 111 | Traversal(&(root.trp.btnd.tnd),&PreorderDFS,&TraceTreap,NULL); 112 | printf("--------------\n"); 113 | BinTreeInorderTraversal( &(root.trp.btnd) ,&TraceTreap,NULL); 114 | 115 | printf("\n Input the num to drag out \n"); 116 | scanf("%d",&i); 117 | 118 | if( i == 0 ) 119 | { 120 | break; 121 | } 122 | 123 | ToFind.i = i; 124 | pFind = BinTreeFind(&root.trp.btnd,&ToFind.trp.btnd,&Test_compare,&Test_eq,NULL); 125 | if(pFind == NULL) 126 | { 127 | printf("unable to find. \n"); 128 | continue; 129 | } 130 | 131 | pFindTest = GET_STRUCT_ADDR( pFind , struct Test , trp.btnd ); 132 | TreapDragOut( &pFindTest->trp ); 133 | tkfree(pFindTest); 134 | } 135 | 136 | printf("allocs = %d \n",g_allocs); 137 | printf("END. \n"); 138 | return 0; 139 | } 140 | -------------------------------------------------------------------------------- /test/demos/tree-demo.c: -------------------------------------------------------------------------------- 1 | #include "headers.h" 2 | #include 3 | 4 | struct Test 5 | { 6 | int level; 7 | int i; 8 | struct BinTreeNode btnd; 9 | }; 10 | 11 | BOOL test_compare(struct BinTreeNode* pa_bigger, 12 | struct BinTreeNode* pa_than, void* pa_else) 13 | { 14 | struct Test* p0 = GET_STRUCT_ADDR( pa_bigger , struct Test , btnd ); 15 | struct Test* p1 = GET_STRUCT_ADDR( pa_than , struct Test , btnd ); 16 | return p0->i > p1->i; 17 | } 18 | 19 | BOOL test_eq(struct BinTreeNode* pa_bigger, 20 | struct BinTreeNode* pa_than, void* pa_else) 21 | { 22 | struct Test* p0 = GET_STRUCT_ADDR( pa_bigger , struct Test , btnd ); 23 | struct Test* p1 = GET_STRUCT_ADDR( pa_than , struct Test , btnd ); 24 | return p0->i == p1->i; 25 | } 26 | 27 | BOOL 28 | LIST_ITERATION_CALLBACK_FUNCTION( TraceBinTree ) 29 | { 30 | struct Branch* pBranch = 31 | GET_STRUCT_ADDR_FROM_IT( pa_pINow , struct Branch , ln); 32 | 33 | struct Test* p = 34 | GET_STRUCT_ADDR( pBranch->pChild , struct Test , btnd.tnd); 35 | 36 | int i; 37 | for(i=0;ilevel;i++) 38 | { 39 | printf(" "); 40 | } 41 | printf("%d at level%d \n", p->i ,p->level ); 42 | 43 | return pa_pINow->now == pa_pIHead->last; 44 | } 45 | 46 | DEF_FREE_TREE_ELEMENT_CALLBACK_FUNCTION( FreeMeAgain , struct Test , btnd.tnd , printf("dele %d \n", pTreeNow->i); ) 47 | 48 | void SetLevel(struct TreeNode* pa_pTnd , int pa_level) 49 | { 50 | struct Test *pTest = GET_STRUCT_ADDR( pa_pTnd , struct Test , btnd.tnd ); 51 | pTest->level = pa_level; 52 | } 53 | 54 | int main() 55 | { 56 | struct Test *p[7]; 57 | struct Test root; 58 | struct Test* pFindTest; 59 | struct BinTreeNode* pFindBTN; 60 | struct Test find; 61 | BinTreeNodeCons(&root.btnd); 62 | int i; 63 | for(i=0;i<7;i++) 64 | { 65 | p[i] = tkmalloc(struct Test); 66 | p[i]->i = i; 67 | p[i]->level = 0; 68 | BinTreeNodeCons(&(p[i]->btnd)); 69 | } 70 | 71 | printf("allocs=%d\n",g_allocs); 72 | 73 | BinAttachTo(&(p[3]->btnd),&(root.btnd),0); 74 | 75 | BinTreeInsert(&(p[1]->btnd),&(p[3]->btnd),&test_compare,NULL); 76 | BinTreeInsert(&(p[5]->btnd),&(p[3]->btnd),&test_compare,NULL); 77 | BinTreeInsert(&(p[0]->btnd),&(p[3]->btnd),&test_compare,NULL); 78 | BinTreeInsert(&(p[2]->btnd),&(p[3]->btnd),&test_compare,NULL); 79 | BinTreeInsert(&(p[4]->btnd),&(p[3]->btnd),&test_compare,NULL); 80 | BinTreeInsert(&(p[6]->btnd),&(p[3]->btnd),&test_compare,NULL); 81 | 82 | TreeGetNodesLevel(&root.btnd.tnd,&SetLevel); 83 | 84 | find.i = 3; 85 | pFindBTN = BinTreeFind(&(p[3]->btnd),&find.btnd,&test_compare,&test_eq,NULL); 86 | if(pFindBTN) 87 | { 88 | pFindTest = GET_STRUCT_ADDR(pFindBTN,struct Test , btnd); 89 | printf("find %d at level%d \n", pFindTest->i ,pFindTest->level ); 90 | } 91 | else 92 | { 93 | printf("not find\n"); 94 | } 95 | 96 | Traversal(&(root.btnd.tnd),&PreorderDFS,&TraceBinTree,NULL); 97 | BinDisattach(&(p[0]->btnd)); 98 | printf("--- --- -- -- \n\n"); 99 | Traversal(&(root.btnd.tnd),&PreorderDFS,&TraceBinTree,NULL); 100 | BinAttachTo(&(p[0]->btnd),&(p[1]->btnd),0); 101 | 102 | printf("Inorder:\n"); 103 | BinTreeInorderTraversal(&(root.btnd),&TraceBinTree,NULL); 104 | printf("PreorderDFS:\n"); 105 | Traversal(&(root.btnd.tnd),&PreorderDFS,&TraceBinTree,NULL); 106 | printf("PostorderDFS:\n"); 107 | Traversal(&(root.btnd.tnd),&PostorderDFS,&TraceBinTree,NULL); 108 | printf("BFS:\n"); 109 | Traversal(&(root.btnd.tnd),&BFS,&TraceBinTree,NULL); 110 | 111 | Traversal(&(root.btnd.tnd),&PostorderDFS,&FreeMeAgain,NULL); 112 | 113 | printf("allocs=%d\n",g_allocs); 114 | 115 | return 0; 116 | } 117 | -------------------------------------------------------------------------------- /test/screenshots/NAT type0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w32zhong/tknet/77d7810abcfdc7cd7bbe556a922fbd7fac37b7a7/test/screenshots/NAT type0.png -------------------------------------------------------------------------------- /test/screenshots/NAT type3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w32zhong/tknet/77d7810abcfdc7cd7bbe556a922fbd7fac37b7a7/test/screenshots/NAT type3.png -------------------------------------------------------------------------------- /test/unit.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/w32zhong/tknet/77d7810abcfdc7cd7bbe556a922fbd7fac37b7a7/test/unit.out -------------------------------------------------------------------------------- /test/unit_test.c: -------------------------------------------------------------------------------- 1 | #include "tknet.h" 2 | 3 | int main() 4 | { 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /tknet.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | #ifndef __TK_NET 15 | #define __TK_NET 16 | 17 | #ifdef _MSC_VER 18 | #pragma warning(disable:4996) 19 | #endif 20 | 21 | #ifdef __cplusplus 22 | extern "C" { 23 | #endif 24 | 25 | #include "head.h" 26 | #include "sysi.h" 27 | 28 | #include "comdef.h" 29 | 30 | #include "list.h" 31 | #include "tree.h" 32 | #include "treap.h" 33 | 34 | //#define TK_CONFIG_SOCK_SSL_ENABLE 35 | #include "sock.h" 36 | 37 | #include "netaddr.h" 38 | #include "netproc.h" 39 | 40 | #include "popmail.h" 41 | #include "base64.h" 42 | #include "smtpmail.h" 43 | 44 | #include "stun.h" 45 | #include "nattype.h" 46 | 47 | struct PeerData; 48 | #include "bdgmsg.h" 49 | #include "relay.h" 50 | #include "peerdata.h" 51 | 52 | #include "keyinfo.h" 53 | #include "pipe.h" 54 | #include "session.h" 55 | #include "nat_checkd.h" 56 | 57 | #include "bkgd.h" 58 | 59 | void 60 | ON_CONNECT(); 61 | 62 | void 63 | tkNetConnect(const char *); 64 | 65 | int 66 | tkNetMain(int ,char **); 67 | 68 | void 69 | tkNetCommonInit(); 70 | 71 | void 72 | tkNetCommonUninit(); 73 | 74 | void 75 | tkNetDefaultPipeInit(); 76 | 77 | void 78 | StdoutPipeFlush(); 79 | 80 | #ifdef __cplusplus 81 | } 82 | #endif 83 | 84 | #endif 85 | -------------------------------------------------------------------------------- /tknet.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | function get_window_id() 3 | { 4 | window_id=$(wmctrl -l | grep "$1" | tail -1 | cut -f1 -d" ") 5 | } 6 | 7 | function set_build_time() 8 | { 9 | echo "#define TKNET_VER \"$(date --rfc-3339=seconds)\"" > head.h 10 | } 11 | 12 | #dependlibs='-lssl -lcrypto -ldl -lpthread' 13 | dependlibs='-lpthread' 14 | 15 | if [ ! $1 ] 16 | then 17 | ./tknet.sh build 18 | 19 | elif [ $1 == 'buildall' ] 20 | then 21 | ./tknet.sh buildarm 22 | ./tknet.sh build 23 | 24 | elif [ $1 == 'buildarm' ] 25 | then 26 | set_build_time 27 | codefiles=`ls | grep '\.c$'` 28 | arm-linux-gcc -c $codefiles 29 | objfiles=`ls | grep '\.o$'` 30 | arm-linux-ar -rcs libtknet.a $objfiles 31 | 32 | arm-linux-gcc -c './test/demo.c' -o ./demo.o 33 | arm-linux-gcc demo.o $dependlibs -L ./ -ltknet -o ./demo 34 | 35 | mkdir -p ./bin/arm 36 | mv libtknet.a ./bin/arm/ 37 | mv demo ./bin/arm/ 38 | cp ./bin/tknet.info ./bin/arm/ 39 | 40 | elif [ $1 == 'build' ] 41 | then 42 | ctags -R * 43 | scons -c 44 | set_build_time 45 | scons 46 | gcc -c './test/demo.c' -o ./demo.o 47 | gcc demo.o -L . -ltknet $dependlibs -o ./demo 48 | 49 | mkdir -p ./bin/x86 50 | mv libtknet.a ./bin/x86/ 51 | mv demo ./bin/x86/ 52 | cp ./bin/tknet.info ./bin/x86/ 53 | 54 | cp ./bin/x86/demo ./test/bin/dir0 55 | cp ./bin/x86/demo ./test/bin/dir1 56 | cp ./bin/x86/demo ./test/bin/dir2 57 | cp ./bin/x86/demo ./test/bin/dir3 58 | 59 | elif [ $1 == 'unit_test' ] 60 | then 61 | gcc -o ./test/unit.out ./test/unit_test.c -I . -L ./bin/x86 -lpthread -ltknet 62 | 63 | elif [ $1 == 'clean' ] 64 | then 65 | objfiles=`ls | grep '\.o$'` 66 | rm -f $objfiles 67 | rm -f tags 68 | rm -rf ./bin/arm 69 | rm -rf ./bin/x86 70 | rm -rf ./dosformat 71 | 72 | rm -f ./test/bin/dir0/demo 73 | rm -f ./test/bin/dir1/demo 74 | rm -f ./test/bin/dir2/demo 75 | rm -f ./test/bin/dir3/demo 76 | 77 | find . -name '*.log' | xargs rm -f 78 | find . -name '*.exp' | xargs rm -f 79 | 80 | elif [ $1 == 'history' ] 81 | then 82 | ./tknet.sh clean 83 | 84 | date --rfc-3339=seconds | grep -o '.*+' > name.tmp 85 | sed -i -e 's/^/tknet /' name.tmp 86 | sed -i -e 's/:/-/g' name.tmp 87 | zipfilename=`sed -e 's/.$/m/' name.tmp ` 88 | rm name.tmp 89 | find . -type d \( -name '.git' -o -name 'history' \) -prune -o -print0 | xargs -0 zip "$zipfilename" 90 | mv *.zip 'history/' 91 | 92 | elif [ $1 == 'test_close' ] 93 | then 94 | for window in $(cat ~/windows.tmp) 95 | do 96 | wmctrl -i -c $window 97 | echo "close $window ..." 98 | done 99 | 100 | elif [ $1 == 'test' ] 101 | then 102 | dir=$(pwd) 103 | rm -f ~/windows.tmp 104 | 105 | wmctrl -o 0,0 106 | gnome-terminal --working-directory="$dir/test/bin/dir0" --command="bash -c 'cat tknet.info;exec bash'" & 107 | sleep 1.5 108 | get_window_id "think-laptop" ; echo "$window_id" >> ~/windows.tmp 109 | wmctrl -i -r "$window_id" -b remove,maximized_horz,maximized_vert 110 | wmctrl -i -r "$window_id" -e 0,0,0,580,300 111 | 112 | gnome-terminal --working-directory="$dir/test/bin/dir1" --command="bash -c 'cat tknet.info;exec bash'" & 113 | sleep 1.5 114 | get_window_id "think-laptop" ; echo "$window_id" >> ~/windows.tmp 115 | wmctrl -i -r "$window_id" -e 0,590,0,580,300 116 | 117 | gnome-terminal --working-directory="$dir/test/bin/dir2" --command="bash -c 'cat tknet.info;exec bash'" & 118 | sleep 1.5 119 | get_window_id "think-laptop" ; echo "$window_id" >> ~/windows.tmp 120 | wmctrl -i -r "$window_id" -e 0,590,320,580,300 121 | 122 | gnome-terminal --working-directory="$dir/test/bin/dir3" --command="bash -c 'cat tknet.info;exec bash'" & 123 | sleep 1.5 124 | get_window_id "think-laptop" ; echo "$window_id" >> ~/windows.tmp 125 | wmctrl -i -r "$window_id" -e 0,0,320,580,300 126 | 127 | elif [ $1 == 'win' ] 128 | then 129 | mkdir -p dosformat 130 | codefiles=`ls | grep '\.[ch]$'` 131 | codefiles+=' test/demo.c' 132 | for file in $codefiles 133 | do 134 | cp $file ./dosformat 135 | done 136 | cd ./dosformat 137 | for file in * 138 | do 139 | sed -i -e 's/$/\r/' $file 140 | done 141 | 142 | elif [ $1 == 'GPL' ] 143 | then 144 | echo '/* 145 | * This file is part of the tknet project. 146 | * which be used under the terms of the GNU General Public 147 | * License version 3.0 as published by the Free Software 148 | * Foundation and appearing in the file LICENSE.GPL included 149 | * in the packaging of this file. Please review the following 150 | * information to ensure the GNU General Public License 151 | * version 3.0 requirements will be met: 152 | * http://www.gnu.org/copyleft/gpl.html 153 | * 154 | * Copyright (C) 2012 Zhong Wei . 155 | */ 156 | ' > GPL.head 157 | 158 | for srcfile in *.c *.h 159 | do 160 | rm -rf ./test/bin 161 | cat GPL.head $srcfile > ${srcfile}.temp 162 | mv ${srcfile}.temp $srcfile 163 | done 164 | rm GPL.head 165 | 166 | elif [ $1 == 'lshead' ] 167 | then 168 | for srcfile in *.c *.h 169 | do 170 | echo "$srcfile:" 171 | cat $srcfile | head -2 172 | done 173 | 174 | elif [ $1 == 'rmhead' ] 175 | then 176 | for srcfile in *.c *.h 177 | do 178 | sed -i '1,9d' $srcfile 179 | done 180 | 181 | else 182 | echo 'input unexpected.' 183 | fi 184 | -------------------------------------------------------------------------------- /treap.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | #include "tknet.h" 15 | 16 | DEF_STRUCT_CONSTRUCTOR( Treap , 17 | out_cons->RanPriority = tkGetRandom(); 18 | BinTreeNodeCons(&out_cons->btnd); 19 | ) 20 | 21 | void 22 | TreapRoateUp(struct Treap* pa_pTp) 23 | { 24 | struct BinTreeNode *pFather,*pGrandpa,*pSave = NULL; 25 | BOOL Pos,FatherPos; 26 | 27 | if( pa_pTp->btnd.tnd.pFather == NULL ) 28 | { 29 | return ; 30 | } 31 | 32 | pFather = GET_STRUCT_ADDR( pa_pTp->btnd.tnd.pFather , struct BinTreeNode , tnd ); 33 | Pos = ( pFather->RightChild == &pa_pTp->btnd ); 34 | BinDisattach(&pa_pTp->btnd); 35 | 36 | if( pFather->tnd.pFather ) 37 | { 38 | pGrandpa = GET_STRUCT_ADDR( pFather->tnd.pFather , struct BinTreeNode , tnd ); 39 | FatherPos = ( pGrandpa->RightChild == pFather ); 40 | BinDisattach(pFather); 41 | 42 | BinAttachTo( &pa_pTp->btnd , pGrandpa , FatherPos ); 43 | } 44 | 45 | if( Pos ) 46 | { 47 | pSave = pa_pTp->btnd.LeftChild; 48 | } 49 | else 50 | { 51 | pSave = pa_pTp->btnd.RightChild; 52 | } 53 | 54 | if( pSave ) 55 | { 56 | BinDisattach( pSave ); 57 | BinAttachTo( pSave , pFather , Pos ); 58 | } 59 | 60 | BinAttachTo( pFather , &pa_pTp->btnd , !Pos ); 61 | } 62 | 63 | void 64 | TreapInsert(struct Treap* pa_pFrom , struct Treap* pa_pTo , BinTreeCompareCallback pa_cmp , void* pa_else) 65 | { 66 | struct TreeNode *pFather; 67 | struct Treap *pFatherTp; 68 | 69 | BinTreeInsert( &pa_pFrom->btnd , &pa_pTo->btnd , pa_cmp , pa_else ); 70 | 71 | while(1) 72 | { 73 | pFather = pa_pFrom->btnd.tnd.pFather; 74 | if( pFather ) 75 | { 76 | pFatherTp = GET_STRUCT_ADDR( pFather , struct Treap , btnd.tnd ); 77 | if( pa_pFrom->RanPriority < pFatherTp->RanPriority ) 78 | { 79 | TreapRoateUp( pa_pFrom ); 80 | } 81 | else 82 | { 83 | break; 84 | } 85 | } 86 | else 87 | { 88 | break; 89 | } 90 | } 91 | } 92 | 93 | void 94 | TreapDragOut( struct Treap* pa_pTp ) 95 | { 96 | struct Treap *pTp; 97 | while(1) 98 | { 99 | if( pa_pTp->btnd.RightChild ) 100 | { 101 | pTp = GET_STRUCT_ADDR( pa_pTp->btnd.RightChild , struct Treap , btnd ); 102 | TreapRoateUp( pTp ); 103 | } 104 | else if( pa_pTp->btnd.LeftChild ) 105 | { 106 | pTp = GET_STRUCT_ADDR( pa_pTp->btnd.LeftChild , struct Treap , btnd ); 107 | TreapRoateUp( pTp ); 108 | } 109 | else 110 | { 111 | break; 112 | } 113 | } 114 | 115 | BinDisattach( &pa_pTp->btnd ); 116 | } 117 | -------------------------------------------------------------------------------- /treap.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | struct Treap 15 | { 16 | uint RanPriority; 17 | struct BinTreeNode btnd; 18 | }; 19 | 20 | DECLARATION_STRUCT_CONSTRUCTOR( Treap ) 21 | 22 | void 23 | TreapRoateUp(struct Treap* ); 24 | 25 | void 26 | TreapInsert(struct Treap* , struct Treap* , BinTreeCompareCallback , void* ); 27 | 28 | void 29 | TreapDragOut( struct Treap* ); 30 | 31 | -------------------------------------------------------------------------------- /tree.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | #include "tknet.h" 15 | 16 | DEF_STRUCT_CONSTRUCTOR( TreeNode , 17 | out_cons->pBranch = NULL; 18 | out_cons->pFather = NULL; 19 | out_cons->IChildren = GetIterator( NULL ); 20 | ) 21 | 22 | void 23 | AttachTo(struct TreeNode* pa_pFrom ,struct TreeNode* pa_pTo ) 24 | { 25 | struct Branch* pNewBranch; 26 | 27 | if(pa_pFrom->pFather != NULL) 28 | { 29 | return; 30 | } 31 | 32 | pNewBranch = tkmalloc( struct Branch ); 33 | ListNodeCons(&pNewBranch->ln); 34 | pNewBranch->pChild = pa_pFrom; 35 | 36 | AddOneToListTail( &pa_pTo->IChildren , &pNewBranch->ln ); 37 | 38 | pa_pFrom->pFather = pa_pTo; 39 | pa_pFrom->pBranch = pNewBranch; 40 | } 41 | 42 | static 43 | DEF_FREE_LIST_ELEMENT_SAFE_FUNCTION( FreeBranchFromList ,struct Branch,ln, ;) 44 | 45 | void 46 | Disattach(struct TreeNode* pa_pTn) 47 | { 48 | struct Iterator IBranch , INextBranch; 49 | 50 | if(pa_pTn->pFather == NULL) 51 | { 52 | return; 53 | } 54 | 55 | IBranch = GetIterator( &pa_pTn->pBranch->ln ); 56 | INextBranch = GetIterator( IBranch.now->next ); 57 | 58 | FreeBranchFromList( &pa_pTn->pFather->IChildren , 59 | &IBranch , 60 | &INextBranch , 61 | NULL); 62 | 63 | pa_pTn->pFather = NULL; 64 | pa_pTn->pBranch = NULL; 65 | } 66 | 67 | struct TreeSearchPa 68 | { 69 | ListNodeCallBack ln_cbk; 70 | void* else_pa; 71 | }; 72 | 73 | BOOL 74 | LIST_ITERATION_CALLBACK_FUNCTION( PreorderDFS ) 75 | { 76 | struct Branch* pBranch = GET_STRUCT_ADDR_FROM_IT( pa_pINow ,struct Branch ,ln ); 77 | struct TreeNode* pChild = pBranch->pChild; 78 | 79 | DEF_AND_CAST( pTspa , struct TreeSearchPa , pa_else ); 80 | 81 | BOOL res = pTspa->ln_cbk( pa_pIHead , pa_pINow , pa_pIForward , pTspa->else_pa ); 82 | 83 | ForEach( &pChild->IChildren , &PreorderDFS , pa_else ); 84 | 85 | return res; 86 | } 87 | 88 | BOOL 89 | LIST_ITERATION_CALLBACK_FUNCTION( PostorderDFS ) 90 | { 91 | struct Branch* pBranch = GET_STRUCT_ADDR_FROM_IT( pa_pINow ,struct Branch ,ln ); 92 | struct TreeNode* pChild = pBranch->pChild; 93 | 94 | DEF_AND_CAST( pTspa , struct TreeSearchPa , pa_else ); 95 | 96 | ForEach( &pChild->IChildren , &PostorderDFS , pa_else ); 97 | 98 | return pTspa->ln_cbk( pa_pIHead , pa_pINow , pa_pIForward , pTspa->else_pa ); 99 | } 100 | 101 | static BOOL 102 | LIST_ITERATION_CALLBACK_FUNCTION( CopyBranchesCallback ) 103 | { 104 | struct Branch* pBranch = GET_STRUCT_ADDR_FROM_IT( pa_pINow ,struct Branch ,ln ); 105 | 106 | DEF_AND_CAST( pITo , struct Iterator , pa_else ); 107 | 108 | struct Branch* pNewBranch = tkmalloc( struct Branch ); 109 | 110 | pNewBranch->pChild = pBranch->pChild; 111 | ListNodeCons( &pNewBranch->ln ); 112 | 113 | AddOneToListTail( pITo , &pNewBranch->ln ); 114 | 115 | return pa_pINow->now == pa_pIHead->last; 116 | } 117 | 118 | BOOL 119 | LIST_ITERATION_CALLBACK_FUNCTION( BFS ) 120 | { 121 | struct Branch* pBranch = GET_STRUCT_ADDR_FROM_IT( pa_pINow ,struct Branch ,ln ); 122 | struct TreeNode* pChild = pBranch->pChild; 123 | 124 | DEF_AND_CAST( pTspa , struct TreeSearchPa , pa_else ); 125 | 126 | ForEach( &pChild->IChildren , &CopyBranchesCallback , pa_pIHead ); 127 | 128 | *pa_pINow = GetIterator( pa_pINow->now ); 129 | *pa_pIForward = GetIterator( pa_pINow->now->next ); 130 | 131 | pTspa->ln_cbk( pa_pINow , pa_pINow , pa_pIForward , pTspa->else_pa ); 132 | 133 | tk( pa_pINow , pa_pIForward ); 134 | tkfree(pBranch); 135 | 136 | *pa_pIHead = *pa_pIForward; 137 | //becaue we will use pa_pIHead to add branches to queue on 138 | //next iteration, we need to make it point to a right position. 139 | 140 | return pa_pINow->now == pa_pIForward->now; 141 | } 142 | 143 | void 144 | Traversal(struct TreeNode* pa_pRoot , ListNodeCallBack pa_TraversalWay , ListNodeCallBack pa_NodeCallback , void* pa_else ) 145 | { 146 | struct TreeSearchPa tspa; 147 | struct Iterator IQueue = GetIterator( NULL ); 148 | tspa.ln_cbk = pa_NodeCallback; 149 | tspa.else_pa = pa_else; 150 | 151 | if( pa_TraversalWay == &BFS) 152 | { 153 | ForEach( &pa_pRoot->IChildren , &CopyBranchesCallback , &IQueue ); 154 | ForEach( &IQueue , &BFS , &tspa ); 155 | } 156 | else 157 | { 158 | ForEach( &pa_pRoot->IChildren , pa_TraversalWay , &tspa ); 159 | } 160 | } 161 | 162 | DEF_STRUCT_CONSTRUCTOR( BinTreeNode , 163 | out_cons->LeftChild = NULL; 164 | out_cons->RightChild = NULL; 165 | TreeNodeCons(&out_cons->tnd); 166 | ) 167 | 168 | void 169 | BinAttachTo(struct BinTreeNode* pa_pFrom , struct BinTreeNode* pa_pTo , BOOL pa_ifRight) 170 | { 171 | if( pa_ifRight ) 172 | { 173 | if(pa_pTo->RightChild) 174 | { 175 | return ; 176 | } 177 | pa_pTo->RightChild = pa_pFrom; 178 | } 179 | else 180 | { 181 | if(pa_pTo->LeftChild) 182 | { 183 | return ; 184 | } 185 | pa_pTo->LeftChild = pa_pFrom; 186 | 187 | } 188 | 189 | AttachTo(&pa_pFrom->tnd,&pa_pTo->tnd); 190 | } 191 | 192 | void 193 | BinDisattach(struct BinTreeNode* pa_pBtn) 194 | { 195 | struct BinTreeNode *pBinFather; 196 | 197 | if( pa_pBtn->tnd.pFather == NULL ) 198 | { 199 | return ; 200 | } 201 | 202 | pBinFather = 203 | GET_STRUCT_ADDR( pa_pBtn->tnd.pFather , struct BinTreeNode , tnd ); 204 | 205 | if( pBinFather->RightChild == pa_pBtn ) 206 | { 207 | pBinFather->RightChild = NULL; 208 | } 209 | else if( pBinFather->LeftChild == pa_pBtn ) 210 | { 211 | pBinFather->LeftChild = NULL; 212 | } 213 | 214 | Disattach( &pa_pBtn->tnd ); 215 | } 216 | 217 | void 218 | BinTreeInsert(struct BinTreeNode* pa_pFrom , struct BinTreeNode* pa_pTo ,BinTreeCompareCallback pa_cmp , void* pa_else) 219 | { 220 | BOOL CompRes = pa_cmp( pa_pFrom , pa_pTo , pa_else ); 221 | 222 | if( CompRes ) 223 | { 224 | if( pa_pTo->RightChild ) 225 | { 226 | BinTreeInsert(pa_pFrom, pa_pTo->RightChild , pa_cmp ,pa_else); 227 | return; 228 | } 229 | } 230 | else 231 | { 232 | if( pa_pTo->LeftChild ) 233 | { 234 | BinTreeInsert(pa_pFrom, pa_pTo->LeftChild , pa_cmp ,pa_else); 235 | return; 236 | } 237 | } 238 | 239 | BinAttachTo(pa_pFrom , pa_pTo , CompRes); 240 | } 241 | 242 | struct BinTreeNode* 243 | BinTreeFind(struct BinTreeNode* pa_pBtn , struct BinTreeNode* pa_pFind , BinTreeCompareCallback pa_cmp ,BinTreeCompareCallback pa_CmpEq , void* pa_else) 244 | { 245 | BOOL CompRes = pa_CmpEq( pa_pBtn , pa_pFind , pa_else ); 246 | 247 | if( CompRes ) 248 | { 249 | return pa_pBtn; 250 | } 251 | 252 | CompRes = pa_cmp( pa_pFind , pa_pBtn , pa_else ); 253 | 254 | if( CompRes ) 255 | { 256 | if( pa_pBtn->RightChild ) 257 | { 258 | return BinTreeFind( pa_pBtn->RightChild , pa_pFind , pa_cmp , pa_CmpEq , pa_else ); 259 | } 260 | } 261 | else 262 | { 263 | if( pa_pBtn->LeftChild ) 264 | { 265 | return BinTreeFind( pa_pBtn->LeftChild , pa_pFind , pa_cmp , pa_CmpEq , pa_else ); 266 | } 267 | } 268 | 269 | return NULL; 270 | } 271 | 272 | static void 273 | _BinTreeInorderTraversal(struct BinTreeNode* pa_pBtn , ListNodeCallBack pa_NodeCallback , void* pa_else ) 274 | { 275 | struct Iterator INow = GetIterator( &(pa_pBtn->tnd.pBranch->ln) ); 276 | struct Iterator IForward = GetIterator( INow.now->next ); 277 | 278 | if( pa_pBtn->LeftChild ) 279 | { 280 | _BinTreeInorderTraversal(pa_pBtn->LeftChild , pa_NodeCallback , pa_else ); 281 | } 282 | 283 | pa_NodeCallback( &(pa_pBtn->tnd.pFather->IChildren) , &INow , &IForward , pa_else ); 284 | 285 | if( pa_pBtn->RightChild ) 286 | { 287 | _BinTreeInorderTraversal(pa_pBtn->RightChild , pa_NodeCallback , pa_else ); 288 | } 289 | } 290 | 291 | void 292 | BinTreeInorderTraversal(struct BinTreeNode* pa_pRoot , ListNodeCallBack pa_NodeCallback , void* pa_else ) 293 | { 294 | struct Branch* pBranch ; 295 | struct BinTreeNode* pChildBinTree; 296 | 297 | if( pa_pRoot->tnd.IChildren.now == NULL ) 298 | { 299 | return; 300 | } 301 | 302 | pBranch = GET_STRUCT_ADDR( pa_pRoot->tnd.IChildren.now , struct Branch , ln ); 303 | pChildBinTree = GET_STRUCT_ADDR( pBranch->pChild , struct BinTreeNode , tnd ); 304 | 305 | _BinTreeInorderTraversal( pChildBinTree , pa_NodeCallback , pa_else ); 306 | } 307 | 308 | struct LevelStackEle 309 | { 310 | uint level; 311 | struct ListNode ln; 312 | }; 313 | 314 | struct GetLevelPa 315 | { 316 | uint level; 317 | struct Iterator LevelStack; 318 | SetLevelCallback slcbk; 319 | }; 320 | 321 | #define IS_LIST_END (pa_pINow->now == pa_pIHead->last) 322 | #define IS_DEPTH_END (pBranch->pChild->IChildren.now == NULL) 323 | 324 | DEF_FREE_LIST_ELEMENT_SAFE_FUNCTION(PopLevelStack,struct LevelStackEle ,ln, ;) 325 | 326 | static BOOL 327 | LIST_ITERATION_CALLBACK_FUNCTION( GetLevelCallback ) 328 | { 329 | struct Branch* pBranch = 330 | GET_STRUCT_ADDR_FROM_IT( pa_pINow , struct Branch , ln); 331 | 332 | DEF_AND_CAST( pGlpa , struct GetLevelPa , pa_else ); 333 | 334 | struct LevelStackEle *pLse; 335 | struct Iterator IForward,*pIHead; 336 | 337 | if( pa_pINow->now == pa_pIHead->now ) 338 | { 339 | pGlpa->level ++; 340 | } 341 | 342 | pGlpa->slcbk( pBranch->pChild , pGlpa->level ); 343 | 344 | if( !IS_LIST_END && !IS_DEPTH_END ) 345 | { 346 | pLse = tkmalloc( struct LevelStackEle ); 347 | ListNodeCons( &pLse->ln ); 348 | pLse->level = pGlpa->level; 349 | AddOneToListHead( &pGlpa->LevelStack , &pLse->ln ); 350 | } 351 | else if( IS_LIST_END && IS_DEPTH_END ) 352 | { 353 | pIHead = &pGlpa->LevelStack; 354 | if(pIHead->now) 355 | { 356 | pLse = GET_STRUCT_ADDR_FROM_IT(pIHead,struct LevelStackEle,ln); 357 | pGlpa->level = pLse->level; 358 | IForward = GetIterator( pIHead->now->next ); 359 | PopLevelStack( pIHead ,pIHead ,&IForward , NULL); 360 | } 361 | } 362 | 363 | return pa_pINow->now == pa_pIHead->last; 364 | } 365 | 366 | void 367 | TreeGetNodesLevel(struct TreeNode* pa_pRoot , SetLevelCallback pa_slcbk) 368 | { 369 | struct GetLevelPa glpa; 370 | glpa.level = 0; 371 | glpa.LevelStack = GetIterator( NULL ); 372 | glpa.slcbk = pa_slcbk; 373 | Traversal(pa_pRoot,&PreorderDFS,&GetLevelCallback,&glpa); 374 | } 375 | -------------------------------------------------------------------------------- /tree.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the tknet project. 3 | * which be used under the terms of the GNU General Public 4 | * License version 3.0 as published by the Free Software 5 | * Foundation and appearing in the file LICENSE.GPL included 6 | * in the packaging of this file. Please review the following 7 | * information to ensure the GNU General Public License 8 | * version 3.0 requirements will be met: 9 | * http://www.gnu.org/copyleft/gpl.html 10 | * 11 | * Copyright (C) 2012 Zhong Wei . 12 | */ 13 | 14 | #define DEF_FREE_TREE_ELEMENT_CALLBACK_FUNCTION( _name , _type_tag , _member_name , _other_statments ) \ 15 | DEF_FREE_LIST_ELEMENT_CALLBACK_FUNCTION( _name , struct Branch , ln , \ 16 | _type_tag * pTreeNow = GET_STRUCT_ADDR( pNow->pChild , _type_tag , _member_name ); \ 17 | _other_statments \ 18 | tkfree(pTreeNow); \ 19 | ) 20 | 21 | struct TreeNode; 22 | 23 | struct Branch 24 | { 25 | struct TreeNode* pChild; 26 | struct ListNode ln; 27 | }; 28 | 29 | struct TreeNode 30 | { 31 | struct Branch *pBranch; 32 | struct TreeNode *pFather; 33 | struct Iterator IChildren; 34 | }; 35 | 36 | DECLARATION_STRUCT_CONSTRUCTOR( TreeNode ) 37 | 38 | void 39 | AttachTo(struct TreeNode* ,struct TreeNode* ); 40 | 41 | void 42 | Disattach(struct TreeNode* ); 43 | 44 | BOOL 45 | LIST_ITERATION_CALLBACK_FUNCTION( PreorderDFS ); 46 | 47 | BOOL 48 | LIST_ITERATION_CALLBACK_FUNCTION( PostorderDFS ); 49 | 50 | BOOL 51 | LIST_ITERATION_CALLBACK_FUNCTION( BFS ); 52 | 53 | void 54 | Traversal(struct TreeNode* , ListNodeCallBack , ListNodeCallBack , void* ); 55 | 56 | struct BinTreeNode 57 | { 58 | struct BinTreeNode *LeftChild,*RightChild; 59 | struct TreeNode tnd; 60 | }; 61 | 62 | DECLARATION_STRUCT_CONSTRUCTOR( BinTreeNode ) 63 | 64 | void 65 | BinAttachTo(struct BinTreeNode* , struct BinTreeNode* , BOOL ); 66 | 67 | void 68 | BinDisattach(struct BinTreeNode* ); 69 | 70 | typedef BOOL (*BinTreeCompareCallback)(struct BinTreeNode* ,struct BinTreeNode* , void*); 71 | 72 | void 73 | BinTreeInsert(struct BinTreeNode* , struct BinTreeNode* ,BinTreeCompareCallback , void* ); 74 | 75 | struct BinTreeNode* 76 | BinTreeFind(struct BinTreeNode* , struct BinTreeNode* , BinTreeCompareCallback ,BinTreeCompareCallback , void* ); 77 | 78 | void 79 | BinTreeInorderTraversal(struct BinTreeNode* , ListNodeCallBack , void* ); 80 | 81 | typedef void (*SetLevelCallback)(struct TreeNode* , uint ); 82 | 83 | void 84 | TreeGetNodesLevel(struct TreeNode* , SetLevelCallback ); 85 | --------------------------------------------------------------------------------