1 /*
2 * This file is part of Licq, an instant messaging client for UNIX.
3 * Copyright (C) 2012 Licq developers <licq-dev@googlegroups.com>
4 *
5 * Licq is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * Licq is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with Licq; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20 #include "socket.h"
21
22 #include <cerrno>
23 #include <sys/socket.h>
24 #include <sys/types.h>
25 #include <unistd.h>
26
27 #include <licq/buffer.h>
28 #include <licq/logging/log.h>
29
30 #include "gettext.h"
31
32 using namespace LicqIcq;
33 using Licq::Buffer;
34 using Licq::gLog;
35
SrvSocket(const Licq::UserId & userId)36 SrvSocket::SrvSocket(const Licq::UserId& userId)
37 : Licq::INetSocket(SOCK_STREAM, "SRV", userId)
38 {
39 // Empty
40 }
41
~SrvSocket()42 SrvSocket::~SrvSocket()
43 {
44 // Empty
45 }
46
47 /*-----SrvSocket::ReceivePacket------------------------------------------------
48 * Receive data on the socket. Checks the buffer to see if it is empty, if
49 * so, then it will create it using either the size read in from the socket
50 * (the first two bytes available) or the given size.
51 *---------------------------------------------------------------------------*/
receiveFlap(Licq::Buffer & buf)52 bool SrvSocket::receiveFlap(Licq::Buffer& buf)
53 {
54 if (!buf.Empty())
55 {
56 gLog.error(tr("Internal error: %s: Called with full buffer (%lu bytes)."),
57 __func__, buf.getDataSize());
58 return true;
59 }
60
61 int nBytesReceived = 0;
62 errno = 0;
63
64 // Check if the buffer is empty
65 char *buffer = new char[6];
66 int nSixBytes = 0;
67 while (nSixBytes != 6)
68 {
69 nBytesReceived = read(myDescriptor, buffer + nSixBytes, 6 - nSixBytes);
70 if (nBytesReceived <= 0)
71 {
72 if (nBytesReceived == 0)
73 gLog.warning(tr("server socket was closed!!!\n"));
74 else
75 {
76 myErrorType = ErrorErrno;
77 gLog.warning(tr("Error during receiving from server socket:\n%s"),
78 errorStr().c_str());
79 }
80 delete[] buffer;
81 return false;
82 }
83 nSixBytes += nBytesReceived;
84 }
85
86 // now we start to verify the FLAP header
87 if (buffer[0] != 0x2a)
88 {
89 gLog.warning(tr("Server send bad packet start code: %02x %02x %02x %02x %02x %02x"),
90 buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]);
91 myErrorType = ErrorErrno;
92 delete[] buffer;
93 return false;
94 }
95
96 // DAW maybe verify sequence number ?
97
98 unsigned short nLen = ((unsigned char)buffer[5]) + (((unsigned char)buffer[4]) << 8);
99
100 // push the 6 bytes at the beginning of the packet again..
101 buf.Create(nLen + 6);
102 buf.packRaw(buffer, 6);
103 delete[] buffer;
104
105 while (!buf.Full())
106 {
107 ssize_t bytesReceived = read(myDescriptor, buf.getDataPosWrite(), buf.remainingDataToWrite());
108 if (bytesReceived == 0 || (bytesReceived < 0 && errno != EINTR))
109 {
110 myErrorType = ErrorErrno;
111 return false;
112 }
113 buf.incDataPosWrite(bytesReceived);
114 }
115
116 DumpPacket(&buf, true);
117
118 return true;
119 }
120
DcSocket(const Licq::UserId & userId)121 DcSocket::DcSocket(const Licq::UserId& userId)
122 : TCPSocket(userId),
123 myVersion(0)
124 {
125 // Empty
126 }
127
DcSocket()128 DcSocket::DcSocket()
129 {
130 // Empty
131 }
132
TransferConnectionFrom(Licq::TCPSocket & from)133 void DcSocket::TransferConnectionFrom(Licq::TCPSocket& from)
134 {
135 DcSocket* dcfrom = dynamic_cast<DcSocket*>(&from);
136 if (dcfrom != NULL)
137 {
138 myVersion = dcfrom->myVersion;
139 }
140
141 Licq::TCPSocket::TransferConnectionFrom(from);
142 }
143
RecvPacket()144 bool DcSocket::RecvPacket()
145 {
146 if (myRecvBuffer.Full())
147 return true;
148
149 if (myRecvBuffer.Empty() || myRecvBuffer.getDataSize() < 2)
150 {
151 // Get header for next packet
152 if (!receive(myRecvBuffer, 2, false))
153 return false;
154
155 if (myRecvBuffer.getDataSize() < 2)
156 {
157 // Didn't get a full header, retry later
158 return true;
159 }
160
161 // Parse packet header
162 int length = myRecvBuffer.unpackUInt16LE();
163
164 // Handle empty packets in case we ever get one
165 if (length == 0)
166 {
167 DumpPacket(&myRecvBuffer, true);
168 return true;
169 }
170
171 // Resize buffer to hold entire packet including the header
172 myRecvBuffer.Create(length + 2);
173 myRecvBuffer.packUInt16LE(length);
174 }
175
176 if (!receive(myRecvBuffer, myRecvBuffer.remainingDataToWrite()))
177 return false;
178
179 return true;
180 }
181