summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorTor Lillqvist <tml@iki.fi>2018-09-15 12:04:05 +0300
committerTor Lillqvist <tml@collabora.com>2018-09-15 12:35:23 +0300
commit0a2868b8d4d3702041ad6f8018f3d4e10a876b44 (patch)
treea456b0ae0bc5e7a88e51169b671e8f29b0f9aae2 /net
parentChange the FakeSocket to be record-oriented (diff)
downloadonline-0a2868b8d4d3702041ad6f8018f3d4e10a876b44.tar.gz
online-0a2868b8d4d3702041ad6f8018f3d4e10a876b44.zip
More FakeSocket hacking
As we use #ifdefs at all call sites anyway (because we don't dare use the generic overrides of close() etc), we can leave out the parameters related to actual BSD sockets that we ignore anyway. "Real" Online always uses non-blocking sockets. We don't need to take flags for that or check it. We can hardcode such behaviour always. (Assuing that is what we want; let's see once something works.) Change-Id: I6863907d71c5599b00ce1f8305a44d41bbaf7bee
Diffstat (limited to 'net')
-rw-r--r--net/FakeSocket.cpp305
-rw-r--r--net/FakeSocket.hpp55
2 files changed, 225 insertions, 135 deletions
diff --git a/net/FakeSocket.cpp b/net/FakeSocket.cpp
index 7477c9755c..e9681b392c 100644
--- a/net/FakeSocket.cpp
+++ b/net/FakeSocket.cpp
@@ -10,15 +10,13 @@
#include <errno.h>
#include <fcntl.h>
+#include <chrono>
#include <condition_variable>
+#include <iostream>
#include <mutex>
+#include <thread>
#include <vector>
-#ifdef TEST
-#include <iostream>
-#define MOBILEAPP
-#endif
-
#include "FakeSocket.hpp"
struct FakeSocketPair
@@ -26,59 +24,66 @@ struct FakeSocketPair
int fd[2];
bool listening;
int connectingFd;
- bool nonblocking[2];
std::vector<char> buffer[2];
std::mutex *mutex;
- std::condition_variable *cv;
+ // std::condition_variable *cv;
FakeSocketPair()
{
fd[0] = -1;
fd[1] = -1;
listening = false;
+ connectingFd = -1;
mutex = new std::mutex();
- cv = new std::condition_variable();
+ // cv = new std::condition_variable();
}
};
static std::mutex fdsMutex;
+static std::condition_variable cv;
-static std::vector<FakeSocketPair> fds;
-
-int fakeSocketSocket(int domain, int type, int protocol)
+// Avoid problems with order of initialisation of static globals.
+static std::vector<FakeSocketPair>& getFds()
{
- if (domain == AF_INET && (type & ~SOCK_NONBLOCK) == SOCK_STREAM && protocol == 0)
- {
- std::lock_guard<std::mutex> fdsLock(fdsMutex);
- size_t i;
- for (i = 0; i < fds.size(); i++)
- {
- if (fds[i].fd[0] == -1 && fds[i].fd[1] == -1)
- break;
- }
- if (i == fds.size())
- fds.resize(fds.size() + 1);
+ static std::vector<FakeSocketPair> fds;
- FakeSocketPair& result = fds[i];
+ return fds;
+}
- result.fd[0] = i*2;
- result.fd[1] = -1;
- result.listening = false;
- result.nonblocking[0] = !!(type & SOCK_NONBLOCK);
- result.buffer[0].resize(0);
- result.buffer[1].resize(0);
+int fakeSocketSocket()
+{
+ std::vector<FakeSocketPair>& fds = getFds();
+ std::cerr << "----- &fds=" << &fds << " size=" << fds.size() << std::endl;
- return i*2;
+ std::lock_guard<std::mutex> fdsLock(fdsMutex);
+ size_t i;
+ for (i = 0; i < fds.size(); i++)
+ {
+ if (fds[i].fd[0] == -1 && fds[i].fd[1] == -1)
+ break;
}
+ if (i == fds.size())
+ fds.resize(fds.size() + 1);
+ FakeSocketPair& result = fds[i];
+
+ result.fd[0] = i*2;
+ result.fd[1] = -1;
+ result.listening = false;
+ result.connectingFd = -1;
+ result.buffer[0].resize(0);
+ result.buffer[1].resize(0);
+
+ std::cerr << "+++++ Created a FakeSocket " << i*2 << "\n";
- errno = EACCES;
- return -1;
+ return i*2;
}
-int fakeSocketPipe2(int pipefd[2], int flags)
+int fakeSocketPipe2(int pipefd[2])
{
- pipefd[0] = fakeSocketSocket(AF_INET, SOCK_STREAM, ((flags & O_NONBLOCK) ? SOCK_NONBLOCK : 0));
+ pipefd[0] = fakeSocketSocket();
+ assert(pipefd[0] >= 0);
+ std::vector<FakeSocketPair>& fds = getFds();
FakeSocketPair& pair = fds[pipefd[0]/2];
std::unique_lock<std::mutex> fdLock(pair.mutex[0]);
@@ -86,22 +91,69 @@ int fakeSocketPipe2(int pipefd[2], int flags)
assert(pair.fd[0] == pipefd[0]);
pair.fd[1] = pair.fd[0] + 1;
- pair.nonblocking[1] = pair.nonblocking[0];
pipefd[1] = pair.fd[1];
+ std::cerr << "+++++ Created a FakeSocket pipe (" << pipefd[0] << "," << pipefd[1] << ")\n";
+
return 0;
}
-int fakeSocketPoll(struct pollfd *fds, int nfds, int timeout)
+static bool someFdReadable(struct pollfd *pollfds, int nfds)
+{
+ std::vector<FakeSocketPair>& fds = getFds();
+ bool retval = false;
+ for (int i = 0; i < nfds; i++)
+ {
+ pollfds[i].revents = 0;
+ const int K = ((pollfds[i].fd)&1);
+ if (pollfds[i].events & POLLIN)
+ if (fds[pollfds[i].fd/2].fd[K] != -1 && fds[pollfds[i].fd/2].buffer[K].size() > 0)
+ {
+ pollfds[i].revents = POLLIN;
+ retval = true;
+ }
+ }
+ return retval;
+}
+
+int fakeSocketPoll(struct pollfd *pollfds, int nfds, int timeout)
{
- return -1;
+ std::cerr << "+++++ Polling " << nfds << " fds: ";
+ for (int i = 0; i < nfds; i++)
+ {
+ if (i > 0)
+ std::cerr << ",";
+ std::cerr << pollfds[i].fd;
+ }
+ std::cerr << "\n";
+
+ std::vector<FakeSocketPair>& fds = getFds();
+ std::unique_lock<std::mutex> fdsLock(fdsMutex);
+ for (int i = 0; i < nfds; i++)
+ {
+ if (pollfds[i].fd < 1 || pollfds[i].fd/2 >= fds.size())
+ {
+ errno = EBADF;
+ return -1;
+ }
+ }
+ // Here we lock just the first FakeSocketPair struct, hmm
+ std::unique_lock<std::mutex> fdLock(fds[pollfds[0].fd/2].mutex[0]);
+ fdsLock.unlock();
+
+ while (!someFdReadable(pollfds, nfds))
+ cv.wait(fdLock);
+
+ return 0;
}
-int fakeSocketListen(int fd, int backlog)
+int fakeSocketListen(int fd)
{
+ std::vector<FakeSocketPair>& fds = getFds();
std::unique_lock<std::mutex> fdsLock(fdsMutex);
if (fd < 0 || fd/2 >= fds.size())
{
+ std::cerr << "+++++ EBADF: Listening on fd " << fd << "\n";
errno = EBADF;
return -1;
}
@@ -112,12 +164,14 @@ int fakeSocketListen(int fd, int backlog)
if (fd&1 || pair.fd[1] != -1)
{
+ std::cerr << "+++++ EISCONN: Listening on fd " << fd << "\n";
errno = EISCONN;
return -1;
}
if (pair.listening)
{
+ std::cerr << "+++++ EIO: Listening on fd " << fd << "\n";
errno = EIO;
return -1;
}
@@ -125,19 +179,24 @@ int fakeSocketListen(int fd, int backlog)
pair.listening = true;
pair.connectingFd = -1;
+ std::cerr << "+++++ Listening on fd " << fd << "\n";
+
return 0;
}
int fakeSocketConnect(int fd1, int fd2)
{
+ std::vector<FakeSocketPair>& fds = getFds();
std::unique_lock<std::mutex> fdsLock(fdsMutex);
if (fd1 < 0 || fd2 < 0 || fd1/2 >= fds.size() || fd2/2 >= fds.size())
{
+ std::cerr << "+++++ EBADF: Connect fd " << fd1 << " to " << fd2 << "\n";
errno = EBADF;
return -1;
}
if (fd1/2 == fd2/2)
{
+ std::cerr << "+++++ EBADF: Connect fd " << fd1 << " to " << fd2 << "\n";
errno = EBADF;
return -1;
}
@@ -151,39 +210,48 @@ int fakeSocketConnect(int fd1, int fd2)
if ((fd1&1) || (fd2&1))
{
+ std::cerr << "+++++ EISCONN: Connect fd " << fd1 << " to " << fd2 << "\n";
errno = EISCONN;
return -1;
}
if (!pair2.listening || pair2.connectingFd != -1)
{
+ std::cerr << "+++++ ECONNREFUSED: Connect fd " << fd1 << " to " << fd2 << "\n";
errno = ECONNREFUSED;
return -1;
}
pair2.connectingFd = fd1;
- pair2.cv->notify_all();
+ // pair2.cv->notify_all();
+ cv.notify_all();
fdLock2.unlock();
while (pair1.fd[1] == -1)
- pair1.cv->wait(fdLock1);
+ // pair1.cv->wait(fdLock1);
+ cv.wait(fdLock1);
assert(pair1.fd[1] == pair1.fd[0] + 1);
+ std::cerr << "+++++ Connect fd " << fd1 << " to " << fd2 << "\n";
+
return 0;
}
-int fakeSocketAccept4(int fd, struct sockaddr *addr, socklen_t *addrlen, int flags)
+int fakeSocketAccept4(int fd, int flags)
{
+ std::vector<FakeSocketPair>& fds = getFds();
std::unique_lock<std::mutex> fdsLock(fdsMutex);
if (fd < 0 || fd/2 >= fds.size())
{
+ std::cerr << "+++++ EBADF: Accept fd " << fd << "\n";
errno = EBADF;
return -1;
}
if (fd & 1)
{
+ std::cerr << "+++++ EISCONN: Accept fd " << fd << "\n";
errno = EISCONN;
return -1;
}
@@ -192,6 +260,7 @@ int fakeSocketAccept4(int fd, struct sockaddr *addr, socklen_t *addrlen, int fla
if (!pair.listening)
{
+ std::cerr << "+++++ EIO: Accept fd " << fd << "\n";
errno = EIO;
return -1;
}
@@ -200,7 +269,8 @@ int fakeSocketAccept4(int fd, struct sockaddr *addr, socklen_t *addrlen, int fla
fdsLock.unlock();
while (pair.connectingFd == -1)
- pair.cv->wait(fdLock);
+ // pair.cv->wait(fdLock);
+ cv.wait(fdLock);
assert(pair.connectingFd >= 0 && pair.connectingFd/2 < fds.size());
@@ -216,13 +286,38 @@ int fakeSocketAccept4(int fd, struct sockaddr *addr, socklen_t *addrlen, int fla
pair1.fd[1] = pair1.fd[0] + 1;
- pair1.cv->notify_one();
+ // pair1.cv->notify_one();
+ cv.notify_one();
+
+ std::cerr << "+++++ Accept fd " << fd << ": " << pair1.fd[1] << "\n";
return pair1.fd[1];
}
+int fakeSocketPeer(int fd)
+{
+ std::vector<FakeSocketPair>& fds = getFds();
+ std::unique_lock<std::mutex> fdsLock(fdsMutex);
+ if (fd < 0 || fd/2 >= fds.size())
+ {
+ errno = EBADF;
+ return -1;
+ }
+
+ FakeSocketPair& pair = fds[fd/2];
+
+ std::unique_lock<std::mutex> fdLock(pair.mutex[0]);
+ fdsLock.unlock();
+
+ const int K = (fd&1);
+ const int N = 1 - K;
+
+ return pair.fd[N];
+}
+
ssize_t fakeSocketAvailableDataLength(int fd)
{
+ std::vector<FakeSocketPair>& fds = getFds();
std::unique_lock<std::mutex> fdsLock(fdsMutex);
if (fd < 0 || fd/2 >= fds.size())
{
@@ -243,9 +338,11 @@ ssize_t fakeSocketAvailableDataLength(int fd)
ssize_t fakeSocketRead(int fd, void *buf, size_t nbytes)
{
+ std::vector<FakeSocketPair>& fds = getFds();
std::unique_lock<std::mutex> fdsLock(fdsMutex);
if (fd < 0 || fd/2 >= fds.size())
{
+ std::cerr << "+++++ EBADF: Read from fd " << fd << ", " << nbytes << (nbytes == 1 ? " byte" : " bytes") << "\n";
errno = EBADF;
return -1;
}
@@ -258,53 +355,91 @@ ssize_t fakeSocketRead(int fd, void *buf, size_t nbytes)
// K: for this fd
const int K = (fd&1);
- if (pair.nonblocking[K])
+ if (pair.fd[K] == -1)
{
- if (pair.fd[K] == -1)
- {
- errno = EBADF;
- return -1;
- }
-
- if (pair.buffer[K].size() == 0)
- {
- errno = EAGAIN;
- return -1;
- }
+ std::cerr << "+++++ EBADF: Read from fd " << fd << ", " << nbytes << (nbytes == 1 ? " byte" : " bytes") << "\n";
+ errno = EBADF;
+ return -1;
}
- else
- {
- while (pair.fd[K] != -1 && pair.buffer[K].size() == 0)
- pair.cv->wait(fdLock);
- if (pair.fd[K] == -1)
- {
- errno = EBADF;
- return -1;
- }
+ if (pair.buffer[K].size() == 0)
+ {
+ std::cerr << "+++++ EAGAIN: Read from fd " << fd << ", " << nbytes << (nbytes == 1 ? " byte" : " bytes") << "\n";
+ errno = EAGAIN;
+ return -1;
}
// These sockets are record-oriented!
ssize_t result = pair.buffer[K].size();
if (nbytes < result)
{
- errno = EAGAIN; // Not the right errno, but what would be?
+ std::cerr << "+++++ EAGAIN: Read from fd " << fd << ", " << nbytes << (nbytes == 1 ? " byte" : " bytes") << "\n";
+ errno = EAGAIN; // Not the right errno, but what would be?q
return -1;
}
memmove(buf, pair.buffer[K].data(), result);
pair.buffer[K].resize(0);
- pair.cv->notify_one();
+ // pair.cv->notify_one();
+ cv.notify_one();
+
+ std::cerr << "+++++ Read from fd " << fd << ": " << result << (result == 1 ? " byte" : " bytes") << "\n";
return result;
}
+ssize_t fakeSocketFeed(int fd, const void *buf, size_t nbytes)
+{
+ std::vector<FakeSocketPair>& fds = getFds();
+ std::unique_lock<std::mutex> fdsLock(fdsMutex);
+ if (fd < 0 || fd/2 >= fds.size())
+ {
+ std::cerr << "+++++ EBADF: Feed to fd " << fd << ", " << nbytes << (nbytes == 1 ? " byte" : " bytes") << "\n";
+ errno = EBADF;
+ return -1;
+ }
+
+ FakeSocketPair& pair = fds[fd/2];
+
+ std::unique_lock<std::mutex> fdLock(pair.mutex[0]);
+ fdsLock.unlock();
+
+ // K: for this fd, whose read buffer we want to write into
+ const int K = (fd&1);
+
+ if (pair.fd[K] == -1)
+ {
+ std::cerr << "+++++ EBADF: Feed to fd " << fd << ", " << nbytes << (nbytes == 1 ? " byte" : " bytes") << "\n";
+ errno = EBADF;
+ return -1;
+ }
+
+ if (pair.buffer[K].size() != 0)
+ {
+ std::cerr << "+++++ EAGAIN: Feed to fd " << fd << ", " << nbytes << (nbytes == 1 ? " byte" : " bytes") << "\n";
+ errno = EAGAIN;
+ return -1;
+ }
+
+ pair.buffer[K].resize(nbytes);
+ memmove(pair.buffer[K].data(), buf, nbytes);
+
+ // pair.cv->notify_one();
+ cv.notify_one();
+
+ std::cerr << "+++++ Feed to fd " << fd << ": " << nbytes << (nbytes == 1 ? " byte" : " bytes") << "\n";
+
+ return nbytes;
+}
+
ssize_t fakeSocketWrite(int fd, const void *buf, size_t nbytes)
{
+ std::vector<FakeSocketPair>& fds = getFds();
std::unique_lock<std::mutex> fdsLock(fdsMutex);
if (fd < 0 || fd/2 >= fds.size())
{
+ std::cerr << "+++++ EBADF: Write to fd " << fd << ", " << nbytes << (nbytes == 1 ? " byte" : " bytes") << "\n";
errno = EBADF;
return -1;
}
@@ -319,45 +454,37 @@ ssize_t fakeSocketWrite(int fd, const void *buf, size_t nbytes)
const int K = (fd&1);
const int N = 1 - K;
- if (pair.nonblocking[K])
+ if (pair.fd[K] == -1)
{
- if (pair.fd[K] == -1)
- {
- errno = EBADF;
- return -1;
- }
-
- if (pair.buffer[N].size() != 0)
- {
- errno = EAGAIN;
- return -1;
- }
+ std::cerr << "+++++ EBADF: Write to fd " << fd << ", " << nbytes << (nbytes == 1 ? " byte" : " bytes") << "\n";
+ errno = EBADF;
+ return -1;
}
- else
- {
- while (pair.fd[K] != -1 && pair.buffer[N].size() != 0)
- pair.cv->wait(fdLock);
- if (pair.fd[K] == -1)
- {
- errno = EBADF;
- return -1;
- }
+ if (pair.buffer[N].size() != 0)
+ {
+ std::cerr << "+++++ EAGAIN: Write to fd " << fd << ", " << nbytes << (nbytes == 1 ? " byte" : " bytes") << "\n";
+ errno = EAGAIN;
+ return -1;
}
pair.buffer[N].resize(nbytes);
memmove(pair.buffer[N].data(), buf, nbytes);
- pair.cv->notify_one();
+ // pair.cv->notify_one();
+ cv.notify_one();
+ std::cerr << "+++++ Write to fd " << fd << ": " << nbytes << (nbytes == 1 ? " byte" : " bytes") << "\n";
return nbytes;
}
int fakeSocketClose(int fd)
{
+ std::vector<FakeSocketPair>& fds = getFds();
std::unique_lock<std::mutex> fdsLock(fdsMutex);
if (fd < 0 || fd/2 >= fds.size())
{
+ std::cerr << "+++++ EBADF: Close fd " << fd << "\n";
errno = EBADF;
return -1;
}
@@ -371,6 +498,8 @@ int fakeSocketClose(int fd)
pair.fd[fd&1] = -1;
+ std::cerr << "+++++ Close fd " << fd << "\n";
+
return 0;
}
diff --git a/net/FakeSocket.hpp b/net/FakeSocket.hpp
index db672b5fc8..e1f89d53c0 100644
--- a/net/FakeSocket.hpp
+++ b/net/FakeSocket.hpp
@@ -13,74 +13,35 @@
#ifdef MOBILEAPP
#include <poll.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <unistd.h>
#ifndef SOCK_NONBLOCK
#define SOCK_NONBLOCK 0x100
#endif
-int fakeSocketSocket(int domain, int type, int protocol);
+int fakeSocketSocket();
-int fakeSocketPipe2(int pipefd[2], int flags);
+int fakeSocketPipe2(int pipefd[2]);
int fakeSocketPoll(struct pollfd *fds, int nfds, int timeout);
-int fakeSocketListen(int fd, int backlog);
+int fakeSocketListen(int fd);
int fakeSocketConnect(int fd1, int fd2);
-int fakeSocketAccept4(int fd, struct sockaddr *addr, socklen_t *addrlen, int flags);
+int fakeSocketAccept4(int fd, int flags);
+
+int fakeSocketPeer(int fd);
ssize_t fakeSocketAvailableDataLength(int fd);
ssize_t fakeSocketRead(int fd, void *buf, size_t nbytes);
+ssize_t fakeSocketFeed(int fd, const void *buf, size_t nbytes);
+
ssize_t fakeSocketWrite(int fd, const void *buf, size_t nbytes);
int fakeSocketClose(int fd);
-inline int socket(int domain, int type, int protocol)
-{
- return fakeSocketSocket(domain, type, protocol);
-}
-
-inline int pipe2(int pipefd[2], int flags)
-{
- return fakeSocketPipe2(pipefd, flags);
-}
-
-inline int poll(struct pollfd *fds, int nfds, int timeout)
-{
- return fakeSocketPoll(fds, nfds, timeout);
-}
-
-inline int listen(int fd, int backlog)
-{
- return fakeSocketListen(fd, backlog);
-}
-
-inline int accept4(int fd, struct sockaddr *addr, socklen_t *addrlen, int flags)
-{
- return fakeSocketAccept4(fd, addr, addrlen, flags);
-}
-
-inline ssize_t read(int fd, void *buf, size_t nbytes)
-{
- return fakeSocketRead(fd, buf, nbytes);
-}
-
-inline ssize_t write(int fd, const void *buf, size_t nbytes)
-{
- return fakeSocketWrite(fd, buf, nbytes);
-}
-
-inline int close(int fd)
-{
- return fakeSocketClose(fd);
-}
-
#endif // MOBILEAPP
#endif // INCLUDED_FAKESOCKET_H