| 1 | #include <errno.h> |
|---|
| 2 | #include <fcntl.h> |
|---|
| 3 | #include "friends_framework.h" |
|---|
| 4 | |
|---|
| 5 | static CoopThreadMgr mgr(new CoopSocketMgr(), new CoopTimeoutMgr(600), 10); |
|---|
| 6 | static sockaddr_in server_addr, my_addr; |
|---|
| 7 | |
|---|
| 8 | struct ProxyConn { |
|---|
| 9 | CoopRunnableSocket<ProxyConn> clientSock; |
|---|
| 10 | CoopRunnableSocket<ProxyConn> serverSock; |
|---|
| 11 | CoopRunnableTimeout<ProxyConn> timeout; |
|---|
| 12 | CoopBuffer dataToServer; |
|---|
| 13 | CoopBuffer dataToClient; |
|---|
| 14 | ProxyConn(int clientFd, sockaddr *, socklen_t) |
|---|
| 15 | : clientSock(&mgr, this, &ProxyConn::OnClientRead, &ProxyConn::OnClientWrite), |
|---|
| 16 | serverSock(&mgr, this, &ProxyConn::OnServerRead, |
|---|
| 17 | &ProxyConn::OnServerConnect), |
|---|
| 18 | timeout(&mgr, this, &ProxyConn::OnTimeout) { |
|---|
| 19 | clientSock.SetSock(clientFd); |
|---|
| 20 | } |
|---|
| 21 | ProxyConn *Init(); |
|---|
| 22 | void ResetTimeout() { |
|---|
| 23 | timeout.SetTimeout(10 * mgr.TicksPerSecond()); |
|---|
| 24 | } |
|---|
| 25 | void OnTimeout(CoopTimeout *) { |
|---|
| 26 | delete this; |
|---|
| 27 | } |
|---|
| 28 | void OnServerConnect(CoopSocket *) { |
|---|
| 29 | ResetTimeout(); |
|---|
| 30 | clientSock.SetWaitForRead(); |
|---|
| 31 | serverSock.SetWaitForRead(); |
|---|
| 32 | serverSock.ClearWaitForWrite(); |
|---|
| 33 | serverSock.writef = &ProxyConn::OnServerWrite; |
|---|
| 34 | } |
|---|
| 35 | void OnClientRead(CoopSocket *) { |
|---|
| 36 | ResetTimeout(); |
|---|
| 37 | if (! CoopTransfer::OnRead(&clientSock, &serverSock, dataToServer)) |
|---|
| 38 | delete this; |
|---|
| 39 | } |
|---|
| 40 | void OnServerWrite(CoopSocket *) { |
|---|
| 41 | ResetTimeout(); |
|---|
| 42 | if (! CoopTransfer::OnWrite(&clientSock, &serverSock, dataToServer)) |
|---|
| 43 | delete this; |
|---|
| 44 | } |
|---|
| 45 | void OnServerRead(CoopSocket *) { |
|---|
| 46 | ResetTimeout(); |
|---|
| 47 | if (! CoopTransfer::OnRead(&serverSock, &clientSock, dataToClient)) |
|---|
| 48 | delete this; |
|---|
| 49 | } |
|---|
| 50 | void OnClientWrite(CoopSocket *) { |
|---|
| 51 | ResetTimeout(); |
|---|
| 52 | if (! CoopTransfer::OnWrite(&serverSock, &clientSock, dataToClient)) |
|---|
| 53 | delete this; |
|---|
| 54 | } |
|---|
| 55 | }; |
|---|
| 56 | |
|---|
| 57 | ProxyConn *ProxyConn::Init() |
|---|
| 58 | { |
|---|
| 59 | serverSock.SetSock(::socket(AF_INET, SOCK_STREAM, 0)); |
|---|
| 60 | assert(serverSock.GetSock() != -1); |
|---|
| 61 | if (::connect(serverSock.GetSock(), reinterpret_cast<sockaddr*>(&server_addr), |
|---|
| 62 | sizeof(server_addr)) == -1) { |
|---|
| 63 | switch (errno) { |
|---|
| 64 | case EAGAIN: |
|---|
| 65 | case EINPROGRESS: |
|---|
| 66 | serverSock.SetWaitForWrite(); |
|---|
| 67 | break; |
|---|
| 68 | default: |
|---|
| 69 | perror("failed to connect to server"); |
|---|
| 70 | delete this; |
|---|
| 71 | return NULL; |
|---|
| 72 | } |
|---|
| 73 | } else { |
|---|
| 74 | OnServerConnect(&serverSock); |
|---|
| 75 | } |
|---|
| 76 | ResetTimeout(); |
|---|
| 77 | return this; |
|---|
| 78 | } |
|---|
| 79 | |
|---|
| 80 | int main(void) |
|---|
| 81 | { |
|---|
| 82 | server_addr.sin_family = AF_INET; |
|---|
| 83 | server_addr.sin_addr.s_addr = htonl(0x7f000001); |
|---|
| 84 | server_addr.sin_port = htons(80); |
|---|
| 85 | |
|---|
| 86 | my_addr.sin_family = AF_INET; |
|---|
| 87 | my_addr.sin_addr.s_addr = htonl(0x7f000001); |
|---|
| 88 | my_addr.sin_port = htons(9999); |
|---|
| 89 | |
|---|
| 90 | if ((new CoopListener<ProxyConn>(&mgr))->Init(reinterpret_cast<sockaddr*>(&my_addr), sizeof(my_addr)) == NULL) |
|---|
| 91 | exit(1); |
|---|
| 92 | |
|---|
| 93 | mgr.Run(); |
|---|
| 94 | |
|---|
| 95 | return 0; |
|---|
| 96 | } |
|---|