You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

171 lines
3.4 KiB

/*
NetworkConnection
High level socket instance wrapper
Author:
Philip Lindsay <follower@rancidbacon.com>
License:
Copyright 2007-2008 // LGPL
*/
#include "connection.h"
int NetworkConnection::_nextSocket = 0;
NetworkConnection::NetworkConnection(uint16_t port) {
/*
Create the low-level socket this instance wraps (for server connections).
*/
_socket = _nextSocket; // TODO: Do properly (& max)
_nextSocket++;
socket(_socket, Sn_MR_TCP, port, 0);
}
NetworkConnection::NetworkConnection() {
/*
Create the low-level socket this instance wraps (for client connections).
*/
NetworkConnection(0);
}
int NetworkConnection::listen() { // TODO: Make private or protected?
/*
Start listening for a connection from a client.
*/
return !!::listen(_socket); // TODO: Use C++ namespaces for the driver functions?
}
int NetworkConnection::connect(uint8 * addr, uint16 port) { // TODO: Make private or protected?
/*
Client connection to a server.
*/
// TODO: Accept bytes here for addr?
int result = 0;
result = !!::connect(_socket, addr, port); // TODO: Use C++ namespaces for the driver functions?
return result;
}
int NetworkConnection::available() {
/*
Functionality matches 'Serial.available()'.
Note: If the socket is not connected then this will return 0,
but it is intended that 'isConnected()' would be checked first.
Returns:
"The number of bytes available to read ... or 0 if none are available.
If any data has come in, [...].available() will be greater than 0."
*/
// TODO: Do we want to check for 'isConnected' as well, or not?
// We have to, I guess, for valid behaviour with 'getSn_*'.
if (!isConnected()) {
return 0;
}
return getSn_RX_RSR(_socket);
}
#define NO_READ_DATA_AVAILABLE -1
int NetworkConnection::read() {
/*
Functionality matches 'Serial.read()'.
Returns:
"an int, the first byte of incoming serial data available
(or -1 if no data is available)."
Note: I thought 'recv' blocked until data was available,
but it currently seems not to block after all.
However, because I'm seeking to match the 'Serial.read'
behaviour we don't actually want to block anyway,
so we'll ignore it for the moment and handle things
ourself for now.
*/
uint8_t theByte;
if (!available()) {
return NO_READ_DATA_AVAILABLE;
}
recv(_socket, &theByte, 1);
return theByte;
}
int NetworkConnection::isConnected() {
/*
Returns true if the connection is established.
*/
// TODO: If we want the 'Network*' classes to be generic we
// would need to handle this differently:
return (getSn_SR(_socket) == SOCK_ESTABLISHED);
}
void NetworkConnection::print(uint8_t b) {
/*
Send a character over connection. Naming matches 'Serial' API.
*/
if (isConnected()) {
send(_socket, &b, 1);
} else {
// Just drop it if we're not connected.
}
}
void NetworkConnection::print(const char * text) {
/*
Send a string over connection. Naming matches 'Serial' API.
*/
for (unsigned int idx = 0; idx < strlen(text); idx++) {
print(text[idx]);
}
}
void NetworkConnection::close() {
/*
Close the connection.
*/
// TODO: Determine if we need/want the disconnect (see pg 26 W5100)
::close(_socket);
disconnect(_socket);
}