Skip to content

Commit

Permalink
Fixed #4
Browse files Browse the repository at this point in the history
  • Loading branch information
velnias75 committed Dec 5, 2014
1 parent 2a8085c commit f01c8c7
Show file tree
Hide file tree
Showing 7 changed files with 204 additions and 56 deletions.
18 changes: 13 additions & 5 deletions src/client/abstractclient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
*/

#include <cstdio>
#include <cstring>

#include "abstractclient.h"

Expand Down Expand Up @@ -70,8 +71,10 @@ using namespace NetMauMau::Client;

AbstractClient::AbstractClient(const std::string &pName, const unsigned char *data, std::size_t len,
const std::string &server, uint16_t port) : IPlayerPicListener(),
m_connection(pName, server, port), m_pName(pName), m_pngData(data), m_pngDataLen(len),
m_cards(), m_openCard(0L), m_disconnectNow(false) {}
m_connection(pName, server, port), m_pName(pName), m_pngData(new unsigned char[len]()),
m_pngDataLen(len), m_cards(), m_openCard(0L), m_disconnectNow(false) {
std::memcpy(m_pngData, data, len);
}

AbstractClient::AbstractClient(const std::string &pName, const std::string &server, uint16_t port)
: IPlayerPicListener(), m_connection(pName, server, port), m_pName(pName), m_pngData(0L),
Expand All @@ -82,6 +85,7 @@ AbstractClient::~AbstractClient() {
for(CARDS::const_iterator i(m_cards.begin()); i != m_cards.end(); ++i) delete *i;

delete m_openCard;
delete [] m_pngData;

m_connection.setInterrupted(false);
}
Expand Down Expand Up @@ -127,7 +131,11 @@ throw(NetMauMau::Common::Exception::SocketException) {
void AbstractClient::play(timeval *timeout) throw(NetMauMau::Common::Exception::SocketException) {

m_connection.setTimeout(timeout);
m_connection.connect(m_pngData, m_pngDataLen);
m_connection.connect(this, m_pngData, m_pngDataLen);

delete [] m_pngData;
m_pngDataLen = 0;
m_pngData = 0L;

const NetMauMau::Common::ICard *lastPlayedCard = 0L;
bool initCardShown = false;
Expand Down Expand Up @@ -193,7 +201,6 @@ void AbstractClient::play(timeval *timeout) throw(NetMauMau::Common::Exception::
&plPicPng(NetMauMau::Common::base64_decode(plPic));

endReceivePlayerPicture(msg);

playerJoined(msg, plPic == "-" ? 0L : plPicPng.data(),
plPic == "-" ? 0 : plPicPng.size());

Expand Down Expand Up @@ -412,7 +419,8 @@ uint16_t AbstractClient::getDefaultPort() {
}

void AbstractClient::beginReceivePlayerPicture(const std::string &) const throw() {}

void AbstractClient::endReceivePlayerPicture(const std::string &) const throw() {}
void AbstractClient::uploadSucceded(const std::string &) const throw() {}
void AbstractClient::uploadFailed(const std::string &) const throw() {}

// kate: indent-mode cstyle; indent-width 4; replace-tabs off; tab-width 4;
30 changes: 24 additions & 6 deletions src/client/clientconnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

#include <sstream>
#include <cstring>
#include <cstdlib>
#include <cerrno>

#ifdef HAVE_UNISTD_H
Expand Down Expand Up @@ -101,7 +102,7 @@ throw(NetMauMau::Common::Exception::SocketException) {
}
#pragma GCC diagnostic pop

Connection::PLAYERINFOS Connection::playerList(const IPlayerPicListener *hdl, bool playerPNG)
Connection::PLAYERINFOS Connection::playerList(const IPlayerPicListener *hdl, bool playerPNG)
throw(NetMauMau::Common::Exception::SocketException) {

PLAYERINFOS plv;
Expand Down Expand Up @@ -191,7 +192,7 @@ throw(NetMauMau::Common::Exception::SocketException) {
return caps;
}

void Connection::connect(const unsigned char *data, std::size_t len)
void Connection::connect(const IPlayerPicListener *l, const unsigned char *data, std::size_t len)
throw(NetMauMau::Common::Exception::SocketException) {

uint16_t maj = 0, min = 0;
Expand All @@ -217,11 +218,28 @@ throw(NetMauMau::Common::Exception::SocketException) {
if(!(data && len)) {
send(m_pName.c_str(), m_pName.length(), getSocketFD());
} else {
const std::string &picPName("+" + m_pName);
const std::string &base64png(NetMauMau::Common::base64_encode(data, len));
try {
const std::string &base64png(NetMauMau::Common::base64_encode(data, len));

send(picPName.c_str(), picPName.length(), getSocketFD());
send(base64png.c_str(), base64png.length(), getSocketFD());
std::ostringstream osp;
osp << "+" << m_pName << '\0' << base64png.length() << '\0' << base64png;

send(osp.str().c_str(), osp.str().length(), getSocketFD());

char ack[1024] = "0";
recv(ack, 1023, getSocketFD());

if(std::strtoul(ack, NULL, 10) == base64png.length()) {
send("OK", 2, getSocketFD());
l->uploadSucceded(m_pName);
} else {
send("NO", 2, getSocketFD());
l->uploadFailed(m_pName);
}

} catch(const NetMauMau::Common::Exception::SocketException &) {
l->uploadFailed(m_pName);
}
}
} else {
throw Exception::ProtocolErrorException("Protocol error", getSocketFD());
Expand Down
46 changes: 26 additions & 20 deletions src/common/abstractsocket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,7 @@ void AbstractSocket::connect() throw(Exception::SocketException) {
std::size_t AbstractSocket::recv(void *buf, std::size_t len,
int fd) throw(Exception::SocketException) {

char rbuf[std::min<std::size_t>(len, 1024)];
char *bufP = static_cast<char *>(buf);
std::size_t total = 0;
ssize_t rlen = -1;

fd_set rfds;
int sret;

Expand All @@ -156,16 +152,23 @@ std::size_t AbstractSocket::recv(void *buf, std::size_t len,

}

while(total < len && (rlen = ::recv(fd, rbuf, std::min<std::size_t>(len, 1024), 0)) > 0) {
total += rlen;
std::memcpy(bufP, rbuf, rlen);
bufP += rlen;
char *ptr = static_cast<char *>(buf);

while(len > 0) {

ssize_t i = ::recv(fd, ptr, len, 0);

if(i < 0) throw Exception::SocketException(std::strerror(errno), fd, errno);

if(rlen <= static_cast<ssize_t>(len)) break;
ptr += i;

if(i < static_cast<ssize_t>(len)) break;

len -= i;
}
}

if(rlen == -1) throw Exception::SocketException(std::strerror(errno), fd, errno);
total = (ptr - static_cast<char *>(buf));
}

return total;
}
Expand All @@ -174,28 +177,31 @@ std::size_t AbstractSocket::recv(void *buf, std::size_t len,
std::string AbstractSocket::read(int fd, std::size_t len) throw(Exception::SocketException) {

std::string ret;
char rbuf[len];
char *rbuf = new char[len];
const std::size_t rlen = recv(rbuf, len, fd);

ret.reserve(rlen);
ret.append(rbuf, rlen);

delete [] rbuf;

return ret;
}

void AbstractSocket::send(const void *buf, std::size_t len,
int fd) throw(Exception::SocketException) {

const char *bufP = static_cast<const char *>(buf);
ssize_t slen = 0;
std::size_t total = 0;
const char *ptr = static_cast<const char *>(buf);

while(total < len && (slen = ::send(fd, bufP, len, MSG_NOSIGNAL)) > 0) {
bufP += slen;
total += slen;
}
while(len > 0) {

if(slen == -1) throw Exception::SocketException(std::strerror(errno), fd, errno);
ssize_t i = ::send(fd, ptr, len, MSG_NOSIGNAL);

if(i < 0) throw Exception::SocketException(std::strerror(errno), fd, errno);

ptr += i;
len -= i;
}
}

void AbstractSocket::write(int fd, const std::string &msg) throw(Exception::SocketException) {
Expand Down
63 changes: 58 additions & 5 deletions src/include/abstractclient.h
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,10 @@ class _EXPORT AbstractClient : protected IPlayerPicListener {
/**
* @brief Returns the list of currently registered player names
*
* @param playerPNG @c true if the player images should get retieved
* @note The image data returned in @c NetMauMau::Client::AbstractClient::PLAYERLIST must
* be freed by the user @code delete [] x->pngData @endcode
*
* @param playerPNG @c true if the player images should get retrieved
* @param timeout the time to wait for a connection, if @c NULL there will be no timeout
*
* @throw Common::Exception::SocketException if the connection failed
Expand All @@ -228,6 +231,10 @@ class _EXPORT AbstractClient : protected IPlayerPicListener {
throw(NetMauMau::Common::Exception::SocketException);

/**
* @brief Returns the list of currently registered player names
*
* It does not retrieve the player images
*
* @overload
*/
PLAYERLIST playerList(timeval *timeout = NULL)
Expand Down Expand Up @@ -391,9 +398,6 @@ class _EXPORT AbstractClient : protected IPlayerPicListener {
virtual void playerJoined(const std::string &player, const unsigned char *pngData,
std::size_t len) const = 0;

virtual void beginReceivePlayerPicture(const std::string &player) const throw() _CONST;
virtual void endReceivePlayerPicture(const std::string &player) const throw() _CONST;

/**
* @brief A player got rejected to join the game
*
Expand Down Expand Up @@ -532,6 +536,55 @@ class _EXPORT AbstractClient : protected IPlayerPicListener {

// @}

/**
* @name Player image notifications
*
* The notifications can be overloaded if the client is interested in events
* regarding the player pictures.
*
* This functions all do nothing at default.
*
* @{
*/

/**
* @brief A download of a player image has started
*
* @param player the player the image is downloaded for
*
* @since 0.4
*/
virtual void beginReceivePlayerPicture(const std::string &player) const throw() _CONST;

/**
* @brief A download of a player image has ended
*
* @param player the player the image is downloaded for
*
* @since 0.4
*/
virtual void endReceivePlayerPicture(const std::string &player) const throw() _CONST;

/**
* @brief The upload of the player image has succeded
*
* @param player the player the image is uploaded for
*
* @since 0.4
*/
virtual void uploadSucceded(const std::string &player) const throw() _CONST;

/**
* @brief The upload of the player image has failed
*
* @param player the player the image is uploaded for
*
* @since 0.4
*/
virtual void uploadFailed(const std::string &player) const throw() _CONST;

/// @}

/**
* @brief The server sent a message not understood by the client
*
Expand All @@ -542,7 +595,7 @@ class _EXPORT AbstractClient : protected IPlayerPicListener {
private:
Connection m_connection;
const std::string m_pName;
const unsigned char *m_pngData;
unsigned char *m_pngData;
std::size_t m_pngDataLen;
CARDS m_cards;
const Common::ICard *m_openCard;
Expand Down
10 changes: 5 additions & 5 deletions src/include/clientconnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ class _EXPORT Connection : public Common::AbstractConnection {
using AbstractConnection::connect;

/**
* @brief tbw
* @brief Holds the name as well as the PNG data of the player image
*/
typedef struct {
std::string name;
const unsigned char *pngData;
std::size_t pngDataLen;
std::string name; ///< the player name
const unsigned char *pngData; ///< raw data of the player image, must be freed by the client
std::size_t pngDataLen; ///< length of the raw data of the player image
} PLAYERINFO;

/**
Expand All @@ -64,7 +64,7 @@ class _EXPORT Connection : public Common::AbstractConnection {
Connection(const std::string &pName, const std::string &server, uint16_t port);
virtual ~Connection();

virtual void connect(const unsigned char *pngData,
virtual void connect(const IPlayerPicListener *l, const unsigned char *pngData,
std::size_t pngDataLen) throw(Common::Exception::SocketException);
CAPABILITIES capabilities() throw(NetMauMau::Common::Exception::SocketException);
PLAYERINFOS playerList(const IPlayerPicListener *hdl,
Expand Down
3 changes: 3 additions & 0 deletions src/include/iplayerpiclistener.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ class IPlayerPicListener {
virtual void beginReceivePlayerPicture(const std::string &player) const throw() = 0;
virtual void endReceivePlayerPicture(const std::string &player) const throw() = 0;

virtual void uploadSucceded(const std::string &player) const throw() = 0;
virtual void uploadFailed(const std::string &player) const throw() = 0;

protected:
IPlayerPicListener() {}
};
Expand Down
Loading

0 comments on commit f01c8c7

Please sign in to comment.