22 #include "mythprotoplayback.h" 23 #include "../private/debug.h" 24 #include "../private/socket.h" 25 #include "../private/os/threads/mutex.h" 26 #include "../private/builtin.h" 34 #include <sys/socket.h> 35 #include <sys/select.h> 45 ProtoPlayback::ProtoPlayback(
const std::string& server,
unsigned port)
50 bool ProtoPlayback::Open()
54 if (!OpenConnection(PROTO_PLAYBACK_RCVBUF))
57 if (m_protoVersion >= 75)
66 void ProtoPlayback::Close()
73 bool ProtoPlayback::IsOpen()
77 return ProtoPlayback::Open();
78 return ProtoBase::IsOpen();
81 bool ProtoPlayback::Announce75()
83 OS::CLockGuard lock(*m_mutex);
85 std::string cmd(
"ANN Playback ");
86 cmd.append(m_socket->GetMyHostName()).append(
" 0");
87 if (!SendCommand(cmd.c_str()))
91 if (!
ReadField(field) || !IsMessageOK(field))
104 OS::CLockGuard lock(*m_mutex);
105 if (!transfer.IsOpen())
107 std::string cmd(
"QUERY_FILETRANSFER ");
108 uint32_to_string(transfer.GetFileId(), buf);
109 cmd.append(buf).append(PROTO_STR_SEPARATOR).append(
"DONE");
110 if (SendCommand(cmd.c_str()))
113 if (!
ReadField(field) || !IsMessageOK(field))
118 bool ProtoPlayback::TransferIsOpen75(
ProtoTransfer& transfer)
124 OS::CLockGuard lock(*m_mutex);
127 std::string cmd(
"QUERY_FILETRANSFER ");
128 uint32_to_string(transfer.GetFileId(), buf);
130 cmd.append(PROTO_STR_SEPARATOR);
131 cmd.append(
"IS_OPEN");
133 if (!SendCommand(cmd.c_str()))
135 if (!
ReadField(field) || 0 != string_to_int8(field.c_str(), &status))
145 int ProtoPlayback::TransferRequestBlock(
ProtoTransfer& transfer,
void *buffer,
unsigned n)
147 bool request =
false, data =
false;
148 int r = 0, nfds = 0, fdc, fdd;
149 char *p = (
char*)buffer;
154 int64_t filePosition = transfer.GetPosition();
155 int64_t fileRequest = transfer.GetRequested();
161 if (INVALID_SOCKET_VALUE == (net_socket_t)fdc)
163 fdd = transfer.GetSocket();
164 if (INVALID_SOCKET_VALUE == (net_socket_t)fdd)
167 if (n > PROTO_TRANSFER_RCVBUF)
168 n = PROTO_TRANSFER_RCVBUF;
169 if ((filePosition + n) > fileRequest)
173 bool ok = TransferRequestBlock75(transfer, n);
187 FD_SET((net_socket_t)fdc, &fds);
191 FD_SET((net_socket_t)fdd, &fds);
208 r = select (nfds + 1, &fds, NULL, NULL, &tv);
211 DBG(DBG_ERROR,
"%s: select error (%d)\n", __FUNCTION__, r);
216 DBG(DBG_ERROR,
"%s: select timeout\n", __FUNCTION__);
221 if (FD_ISSET((net_socket_t)fdd, &fds))
223 r = recv((net_socket_t)fdd, p, (
size_t)(n - s), 0);
226 DBG(DBG_ERROR,
"%s: recv data error (%d)\n", __FUNCTION__, r);
235 transfer.SetPosition(filePosition);
239 if (request && FD_ISSET((net_socket_t)fdc, &fds))
241 int32_t rlen = TransferRequestBlockFeedback75();
246 DBG(DBG_DEBUG,
"%s: receive block size (%u)\n", __FUNCTION__, (
unsigned)rlen);
247 if (rlen == 0 && !data)
250 transfer.SetRequested(fileRequest);
252 }
while (request || data || !s);
253 DBG(DBG_DEBUG,
"%s: data read (%u)\n", __FUNCTION__, s);
258 if (RcvMessageLength())
263 if (TransferSeek(transfer, filePosition, WHENCE_SET) < 0)
268 bool ProtoPlayback::TransferRequestBlock75(
ProtoTransfer& transfer,
unsigned n)
273 if (!transfer.IsOpen())
275 std::string cmd(
"QUERY_FILETRANSFER ");
276 uint32_to_string(transfer.GetFileId(), buf);
278 cmd.append(PROTO_STR_SEPARATOR);
279 cmd.append(
"REQUEST_BLOCK");
280 cmd.append(PROTO_STR_SEPARATOR);
281 uint32_to_string(n, buf);
285 if (!SendCommand(cmd.c_str(),
false))
290 int32_t ProtoPlayback::TransferRequestBlockFeedback75()
294 if (!RcvMessageLength() || !
ReadField(field) || 0 != string_to_int32(field.c_str(), &rlen) || rlen < 0)
296 DBG(DBG_ERROR,
"%s: invalid response for request block (%s)\n", __FUNCTION__, field.c_str());
303 int64_t ProtoPlayback::TransferSeek75(
ProtoTransfer& transfer, int64_t offset, WHENCE_t whence)
306 int64_t position = 0;
309 int64_t filePosition = transfer.GetPosition();
310 int64_t fileSize = transfer.GetSize();
318 position = filePosition + offset;
319 if (position < 0 || position > fileSize)
323 if (offset == filePosition)
325 if (offset < 0 || offset > fileSize)
329 position = fileSize - offset;
330 if (position < 0 || position > fileSize)
337 OS::CLockGuard lock(*m_mutex);
338 if (!transfer.IsOpen())
340 std::string cmd(
"QUERY_FILETRANSFER ");
341 uint32_to_string(transfer.GetFileId(), buf);
343 cmd.append(PROTO_STR_SEPARATOR);
345 cmd.append(PROTO_STR_SEPARATOR);
346 int64_to_string(offset, buf);
348 cmd.append(PROTO_STR_SEPARATOR);
349 int8_to_string(whence, buf);
351 cmd.append(PROTO_STR_SEPARATOR);
352 int64_to_string(filePosition, buf);
355 if (!SendCommand(cmd.c_str()))
357 if (!
ReadField(field) || 0 != string_to_int64(field.c_str(), &position))
364 transfer.SetRequested(position);
365 transfer.SetPosition(position);
void Flush()
Flushing unread data previously requested.
bool m_hang
Connection hang: while true allow retry.
bool ReadField(std::string &field)
This is the main namespace that encloses all public classes.
bool m_tainted
Connection has hung since last reset.