PN532 not working as expected with I2C communication with ESP8266 NodeMCU v3 - nfc

I have two problems with the PN532 connected with I2C communication in the ESP8266.
The first problem is that sometimes when I connect the board, it throws an error saying that it didn't find the PN53X board
Didn't find PN53x board
0x40237dbc in NfcAdapter::begin(bool) at lib\NDEF/NfcAdapter.cpp:22 (discriminator 1)
0x4023571a in setup at src/main.cpp:34
0x4023a827 in loop_wrapper() at C:\Users\joaqu\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/core_esp8266_main.cpp:198
0x40101229 in cont_wrapper at C:\Users\joaqu\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/cont.S:81
Then the program restarts, and the same error shows until I disconnect the PN532 from power and connect it again. Only then the program starts. If I hit the RST button from the microprocessor before doing this, it shows the same error. If I hit it after, doing it, it may just start the program, or show the same error. The only constant is that when the error shows, the only way for the program to start is to disconnect and reconnect the PN532.
I thought it may be something with the fact that I am using a protoboard and maybe the cables disconnect just when I connect the board, but the light is on all the time, and if this was the case, then using the RST button should work.
The other problem is that after executing the program without reading for a "long" time, the system throws a VERY long error that has 2 lines related to the PN532, and the system restarts, and the previous problem always presents itself because of the restart.
Here is the error:
0x4023af38 in Twi::read_byte(bool) at C:\Users\joaqu\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/core_esp8266_si2c.cpp:315 (discriminator 2)
0x4023b0a4 in Twi::readFrom(unsigned char, unsigned char*, unsigned int, unsigned char) at C:\Users\joaqu\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/core_esp8266_si2c.cpp:383 (discriminator 2)
0x4023b2e0 in twi_readFrom at C:\Users\joaqu\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/core_esp8266_si2c.cpp:989
0x401061a9 in ets_timer_arm_new at ??:?
0x4023b2e0 in twi_readFrom at C:\Users\joaqu\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/core_esp8266_si2c.cpp:989
0x4023b39c in __delay at C:\Users\joaqu\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/core_esp8266_wiring.cpp:49
0x40237c30 in TwoWire::requestFrom(unsigned char, unsigned int, bool) at C:\Users\joaqu\.platformio\packages\framework-arduinoespressif8266\libraries\Wire/Wire.cpp:129
0x4023b3b5 in __delay at C:\Users\joaqu\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/core_esp8266_wiring.cpp:57
0x40237c63 in TwoWire::requestFrom(int, int) at C:\Users\joaqu\.platformio\packages\framework-arduinoespressif8266\libraries\Wire/Wire.cpp:148
0x40238b36 in PN532_I2C::readResponse(unsigned char*, unsigned char, unsigned short) at lib\PN532_I2C/PN532_I2C.cpp:126
0x40105f25 in wdt_feed at ??:?
0x40248869 in PN532::readPassiveTargetID(unsigned char, unsigned char*, unsigned char*, unsigned short) at lib\PN532/PN532.cpp:393
0x40237e01 in NfcAdapter::tagPresent(unsigned long) at lib\NDEF/NfcAdapter.cpp:42
0x40235904 in readNFC(NfcAdapter*) at src/readNFC.cpp:11
0x401058cd in call_user_start_local at ??:?
0x401058d3 in call_user_start_local at ??:?
0x40100df4 in umm_init at C:\Users\joaqu\.platformio\packages\framework-arduinoespressif8266\cores\esp8266\umm_malloc/umm_malloc.cpp:478
0x4010000d in call_user_start at ??:?
0x401000ab in app_entry_redefinable at C:\Users\joaqu\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/core_esp8266_main.cpp:325
0x40269790 in cont_ret at C:\Users\joaqu\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/cont.S:142
0x402357ab in String::isSSO() const at C:\Users\joaqu\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/WString.h:262
(inlined by) String::wbuffer() const at C:\Users\joaqu\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/WString.h:277
(inlined by) String::buffer() const at C:\Users\joaqu\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/WString.h:276
(inlined by) String::operator bool() const at C:\Users\joaqu\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/WString.h:139
(inlined by) loop at src/main.cpp:47
0x4023a41a in loop_wrapper() at C:\Users\joaqu\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/core_esp8266_main.cpp:201
0x40101229 in cont_wrapper at C:\Users\joaqu\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/cont.S:81
0x40212180 in sqlite3VXPrintf at .pio\libdeps\esp12e\Sqlite3 for ESP8266\src/sqlite3.c:25485 (discriminator 1)
0x40212159 in sqlite3VXPrintf at .pio\libdeps\esp12e\Sqlite3 for ESP8266\src/sqlite3.c:25484 (discriminator 1)
0x40212b8d in sqlite3VXPrintf at .pio\libdeps\esp12e\Sqlite3 for ESP8266\src/sqlite3.c:25815
0x40219b9e in lookupName at .pio\libdeps\esp12e\Sqlite3 for ESP8266\src/sqlite3.c:89826
0x4024f0b4 in __ssputs_r at /workdir/repo/newlib/newlib/libc/stdio/nano-vfprintf.c:232
0x4024ad0d in _printf_i at /workdir/repo/newlib/newlib/libc/stdio/nano-vfprintf_i.c:196 (discriminator 1)
0x4024f0b4 in __ssputs_r at /workdir/repo/newlib/newlib/libc/stdio/nano-vfprintf.c:232
0x4024eff0 in __ssputs_r at /workdir/repo/newlib/newlib/libc/stdio/nano-vfprintf.c:179
0x40219c10 in resolveExprStep at .pio\libdeps\esp12e\Sqlite3 for ESP8266\src/sqlite3.c:89917
0x40219498 in resolveSelectStep at .pio\libdeps\esp12e\Sqlite3 for ESP8266\src/sqlite3.c:90505
0x4024ae3c in _printf_i at /workdir/repo/newlib/newlib/libc/stdio/nano-vfprintf_i.c:246
0x4027f1af in chip_v6_unset_chanfreq at ??:?
0x4024eff0 in __ssputs_r at /workdir/repo/newlib/newlib/libc/stdio/nano-vfprintf.c:179
0x4024f505 in _svfprintf_r at /workdir/repo/newlib/newlib/libc/stdio/nano-vfprintf.c:662
0x4020e8e6 in sqlite3MemFree at .pio\libdeps\esp12e\Sqlite3 for ESP8266\src/sqlite3.c:20819
0x40100e4d in malloc at C:\Users\joaqu\.platformio\packages\framework-arduinoespressif8266\cores\esp8266\umm_malloc/umm_malloc.cpp:821
0x402140bc in sqlite3MemMalloc at .pio\libdeps\esp12e\Sqlite3 for ESP8266\src/sqlite3.c:20790
0x402013ac in sqlite3Malloc at .pio\libdeps\esp12e\Sqlite3 for ESP8266\src/sqlite3.c:24497
0x40100e4d in malloc at C:\Users\joaqu\.platformio\packages\framework-arduinoespressif8266\cores\esp8266\umm_malloc/umm_malloc.cpp:821
0x40201618 in dbMallocRawFinish at .pio\libdeps\esp12e\Sqlite3 for ESP8266\src/sqlite3.c:24825
0x4020163d in sqlite3DbMallocRawNN at .pio\libdeps\esp12e\Sqlite3 for ESP8266\src/sqlite3.c:24893
0x4020eb0a in sqlite3DbRealloc at .pio\libdeps\esp12e\Sqlite3 for ESP8266\src/sqlite3.c:24905 (discriminator 1)
0x4020f21a in growOpArray at .pio\libdeps\esp12e\Sqlite3 for ESP8266\src/sqlite3.c:71547
0x4020f26c in growOp3 at .pio\libdeps\esp12e\Sqlite3 for ESP8266\src/sqlite3.c:71585
0x402140bc in sqlite3MemMalloc at .pio\libdeps\esp12e\Sqlite3 for ESP8266\src/sqlite3.c:20790
0x402044da in resolveP2Values at .pio\libdeps\esp12e\Sqlite3 for ESP8266\src/sqlite3.c:72048
0x40207855 in sqlite3VdbeMakeReady at .pio\libdeps\esp12e\Sqlite3 for ESP8266\src/sqlite3.c:73389
0x4020f7a8 in allocVdbe at .pio\libdeps\esp12e\Sqlite3 for ESP8266\src/sqlite3.c:118355
0x4021eccf in sqlite3FinishCoding at .pio\libdeps\esp12e\Sqlite3 for ESP8266\src/sqlite3.c:99926
0x40231006 in yy_reduce at .pio\libdeps\esp12e\Sqlite3 for ESP8266\src/sqlite3.c:137400
0x40231006 in yy_reduce at .pio\libdeps\esp12e\Sqlite3 for ESP8266\src/sqlite3.c:137400
0x402323e8 in sqlite3Parser at .pio\libdeps\esp12e\Sqlite3 for ESP8266\src/sqlite3.c:138590
0x40208cf4 in yy_pop_parser_stack at .pio\libdeps\esp12e\Sqlite3 for ESP8266\src/sqlite3.c:136856
0x40208d0e in sqlite3ParserFinalize at .pio\libdeps\esp12e\Sqlite3 for ESP8266\src/sqlite3.c:136863 (discriminator 1)
0x402325a5 in sqlite3RunParser at .pio\libdeps\esp12e\Sqlite3 for ESP8266\src/sqlite3.c:139431
Just because, here is the code I am running:
// NFC
PN532_I2C pn532_i2c(Wire);
NfcAdapter nfc = NfcAdapter(pn532_i2c);
// RTC
RTClib RTC;
void setup() {
Serial.begin(9600);
Wire.begin();
nfc.begin();
// Start the SD Card and the database
SPI.begin();
if (vfs_mount("/SD0", D8) == NULL) {
Serial.println("SD Card Mount Failed");
return;
}
sqlite3_initialize();
Serial.println("System Ready");
}
void loop() {
// Read the NFC tag
String tagId = readNFC(&nfc);
if (tagId && !tagId[0]) return;
// Query the tag
char *message = "";
if (!query_tag(tagId.c_str(), &message)) return;
// Print the message
if (message && !message[0]) {
// If the message is empty, ask the user if they want to save a message
Serial.println("Tag not found\n");
Serial.println("Do you want to save the tag? (y/n)");
// Wait for the user to enter a character
while (Serial.available() == 0) delay(100);
char c = Serial.read();
if (c != 'y') {
Serial.println("Tag not saved");
return;
}
// If the user enters 'y', ask for the message
Serial.println("Enter the message:");
while (Serial.available() == 0) delay(100);
String message = Serial.readString();
if (!message && !message[0]) {
Serial.println("Message cannot be empty\nTag not saved");
}
if (!save_tag(tagId.c_str(), message.c_str())) return;
} else {
Serial.printf("%s\n\n", message);
return;
}
}
byte nuidPICC[6];
String readNFC(NfcAdapter *nfc) {
if (!nfc->tagPresent()) return "";
NfcTag tag = nfc->read();
String tagId = tag.getUidString();
Serial.println(tagId);
return tagId;
}
sqlite3 *db = NULL;
char *db_file_name = "/SD0/sqlite.db";
/**
* Open data.db
*
* #return
*/
bool db_open() {
// Close the database if it's already open
if (db != NULL) sqlite3_close(db);
// Open the database
if (sqlite3_open_v2(db_file_name, &db,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
NULL) == SQLITE_OK) {
Serial.println(F("Opened database successfully"));
return true;
}
// If the database can't be opened, print an error
Serial.print(F("Can't open database: "));
Serial.println(sqlite3_errmsg(db));
return false;
}
/**
* Query the tag in the database
*
* #param tag The tag to query
* #param db The database
*
* #return 1 if the tag is found, 0 otherwise
*/
bool query_tag(const char *tag, char **message) {
// Open the database
if (!db_open()) return false;
const char *null;
// Prepare the statement
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(db, "SELECT value FROM nfc_tag WHERE id = ?;", -1,
&statement, &null) != SQLITE_OK) {
Serial.print("Unable to prepare: ");
Serial.println(sqlite3_errmsg(db));
return false;
}
// Bind the value
if (sqlite3_bind_text(statement, 1, tag, -1, SQLITE_TRANSIENT) != SQLITE_OK) {
Serial.print("Unable to bind text: ");
Serial.println(sqlite3_errmsg(db));
sqlite3_finalize(statement);
return false;
}
if (sqlite3_step(statement) != SQLITE_DONE) {
const unsigned char *value = sqlite3_column_text(statement, 0);
// Check value and save it in message
if (value)
*message = const_cast<char *>(reinterpret_cast<const char *>(value));
}
sqlite3_finalize(statement);
// Close the database
db_close();
return true;
}
/**
* Close the database
*/
void db_close() {
if (db != NULL) sqlite3_close(db);
db = NULL;
Serial.println("Closed database successfully");
return;
}
/**
* Save new tags to the database
*
* #param tag The tag to save
* #param message The message to save
*
* #return True if the tag is saved, false otherwise
*/
bool save_tag(const char *tag, const char *message) {
// Open the database
if (!db_open()) return false;
// Prepare the statement
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(db, "INSERT INTO nfc_tag (id, value) VALUES (?, ?);",
-1, &statement, NULL) != SQLITE_OK) {
Serial.print("Unable to prepare: ");
Serial.println(sqlite3_errmsg(db));
return false;
}
// Bind the values
if (sqlite3_bind_text(statement, 1, tag, -1, SQLITE_TRANSIENT) != SQLITE_OK) {
Serial.print("Unable to bind tag: ");
Serial.println(sqlite3_errmsg(db));
sqlite3_finalize(statement);
return false;
}
if (sqlite3_bind_text(statement, 2, message, -1, SQLITE_TRANSIENT) !=
SQLITE_OK) {
Serial.print("Unable to bind message: ");
Serial.println(sqlite3_errmsg(db));
sqlite3_finalize(statement);
return false;
}
// Execute the statement
sqlite3_step(statement);
sqlite3_finalize(statement);
// Close the database
db_close();
return true;
}

Related

Whats the purpose of "num" in arduinoWebSockets?

Whats the purpose of num in webSocket.sendTXT(num, "Connected"); or at any other place its used in the code, what function does it serve? Because it doesn't ever get defined as anything anywhere, but it is required to
be passed as a function argument for it to work.
In void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) it's set as a function parameter.
Links2004/arduinoWebSockets Library
/*
* WebSocketServer_LEDcontrol.ino
*
* Created on: 26.11.2015
*
*/
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <WebSocketsServer.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <Hash.h>
#define LED_RED 15
#define LED_GREEN 12
#define LED_BLUE 13
#define USE_SERIAL Serial
ESP8266WiFiMulti WiFiMulti;
ESP8266WebServer server = ESP8266WebServer(80);
WebSocketsServer webSocket = WebSocketsServer(81);
void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length) {
switch(type) {
case WStype_DISCONNECTED:
USE_SERIAL.printf("[%u] Disconnected!\n", num);
break;
case WStype_CONNECTED: {
IPAddress ip = webSocket.remoteIP(num);
USE_SERIAL.printf("[%u] Connected from %d.%d.%d.%d url: %s\n", num, ip[0], ip[1], ip[2], ip[3], payload);
// send message to client
webSocket.sendTXT(num, "Connected");
}
break;
case WStype_TEXT:
USE_SERIAL.printf("[%u] get Text: %s\n", num, payload);
if(payload[0] == '#') {
// we get RGB data
// decode rgb data
uint32_t rgb = (uint32_t) strtol((const char *) &payload[1], NULL, 16);
analogWrite(LED_RED, ((rgb >> 16) & 0xFF));
analogWrite(LED_GREEN, ((rgb >> 8) & 0xFF));
analogWrite(LED_BLUE, ((rgb >> 0) & 0xFF));
}
break;
}
}
void setup() {
//USE_SERIAL.begin(921600);
USE_SERIAL.begin(115200);
//USE_SERIAL.setDebugOutput(true);
USE_SERIAL.println();
USE_SERIAL.println();
USE_SERIAL.println();
for(uint8_t t = 4; t > 0; t--) {
USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t);
USE_SERIAL.flush();
delay(1000);
}
pinMode(LED_RED, OUTPUT);
pinMode(LED_GREEN, OUTPUT);
pinMode(LED_BLUE, OUTPUT);
digitalWrite(LED_RED, 1);
digitalWrite(LED_GREEN, 1);
digitalWrite(LED_BLUE, 1);
WiFiMulti.addAP("SSID", "passpasspass");
while(WiFiMulti.run() != WL_CONNECTED) {
delay(100);
}
// start webSocket server
webSocket.begin();
webSocket.onEvent(webSocketEvent);
if(MDNS.begin("esp8266")) {
USE_SERIAL.println("MDNS responder started");
}
// handle index
server.on("/", []() {
// send index.html
server.send(200, "text/html", "<html><head><script>var connection = new WebSocket('ws://'+location.hostname+':81/', ['arduino']);connection.onopen = function () { connection.send('Connect ' + new Date()); }; connection.onerror = function (error) { console.log('WebSocket Error ', error);};connection.onmessage = function (e) { console.log('Server: ', e.data);};function sendRGB() { var r = parseInt(document.getElementById('r').value).toString(16); var g = parseInt(document.getElementById('g').value).toString(16); var b = parseInt(document.getElementById('b').value).toString(16); if(r.length < 2) { r = '0' + r; } if(g.length < 2) { g = '0' + g; } if(b.length < 2) { b = '0' + b; } var rgb = '#'+r+g+b; console.log('RGB: ' + rgb); connection.send(rgb); }</script></head><body>LED Control:<br/><br/>R: <input id=\"r\" type=\"range\" min=\"0\" max=\"255\" step=\"1\" oninput=\"sendRGB();\" /><br/>G: <input id=\"g\" type=\"range\" min=\"0\" max=\"255\" step=\"1\" oninput=\"sendRGB();\" /><br/>B: <input id=\"b\" type=\"range\" min=\"0\" max=\"255\" step=\"1\" oninput=\"sendRGB();\" /><br/></body></html>");
});
server.begin();
// Add service to MDNS
MDNS.addService("http", "tcp", 80);
MDNS.addService("ws", "tcp", 81);
digitalWrite(LED_RED, 0);
digitalWrite(LED_GREEN, 0);
digitalWrite(LED_BLUE, 0);
}
void loop() {
webSocket.loop();
server.handleClient();
}
Looking at the library's source code, it reveals that it's a client id, so you can differentiate between multiple clients, that are connected at the same time.
/*
* send text data to client
* #param num uint8_t client id
* #param payload uint8_t *
* #param length size_t
* #param headerToPayload bool (see sendFrame for more details)
* #return true if ok
*/
bool WebSocketsServer::sendTXT(uint8_t num, uint8_t * payload, size_t length, bool headerToPayload) {
if(num >= WEBSOCKETS_SERVER_CLIENT_MAX) {
return false;
}
if(length == 0) {
length = strlen((const char *) payload);
}
WSclient_t * client = &_clients[num];
if(clientIsConnected(client)) {
return sendFrame(client, WSop_text, payload, length, false, true, headerToPayload);
}
return false;
}

Browse LDAP servers in the domain

I am following this guide.
I used the following code to display LDAP servers in the domain:
#include <dns_sd.h>
#include <stdio.h>
#include <pthread.h>
void ResolveCallBack(DNSServiceRef sdRef,
DNSServiceFlags flags,
uint32_t interfaceIndex,
DNSServiceErrorType errorCode,
const char *fullname,
const char *hosttarget,
uint16_t port, /* In network byte order */
uint16_t txtLen,
const unsigned char *txtRecord,
void *context) {
}
void BrowserCallBack(DNSServiceRef inServiceRef,
DNSServiceFlags inFlags,
uint32_t inIFI,
DNSServiceErrorType inError,
const char* inName,
const char* inType,
const char* inDomain,
void* inContext) {
DNSServiceErrorType err = DNSServiceResolve(&inServiceRef,
0, // Indicate it's a shared connection.
inIFI,
inName,
inType,
inDomain,
ResolveCallBack,
NULL);
printf("DNSServiceResolve err = %x, name = %s, type=%s, domain=%s\n",
err, inName, inType, inDomain);
}
int main() {
DNSServiceRef ServiceRef;
DNSServiceErrorType err = DNSServiceBrowse(&ServiceRef, // Receives reference to Bonjour browser object.
kDNSServiceFlagsDefault, // Indicate it's a shared connection.
kDNSServiceInterfaceIndexAny, // Browse on all network interfaces.
"_ldap._tcp", // Browse for service types.
NULL, // Browse on the default domain (e.g. local.).
BrowserCallBack, // Callback function when Bonjour events occur.
NULL); // Callback context.
printf("err = 0x%x\n", err);
int sockfd = DNSServiceRefSockFD(ServiceRef);
printf("sockfd = %d\n", sockfd);
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, 0);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
struct timeval timeout;
timeout.tv_sec = 1;
timeout.tv_usec = 0;
fd_set descriptors;
FD_ZERO(&descriptors);
FD_SET(sockfd, &descriptors);
int r = select(sockfd + 1, &descriptors, NULL, NULL, &timeout);
printf("r = %d\n", r);
fflush(stdout);
if (r > 0) {
if (FD_ISSET(sockfd, &descriptors)) {
// This function will call the appropiate callback to process the
// event, in this case the BrowseReply static method.
err = DNSServiceProcessResult(ServiceRef);
if (err != kDNSServiceErr_NoError) {
printf("Error on process an event in event loop, e = 0x%x\n", err);
}
}
} else if (r == -1) {
printf("The select() call failed");
}
return 0;
}
However, this didn't give me any LDAP server.
Any Help on this?
Thanks in advance
N.B:
This command returns results:
$nslookup -type=any _ldap._tcp
So there is LDAP servers in the domain.
When I tried "_http._tcp" as the registration type this returns
results.
Operating system is Mac OS X 10.9.

Migrating Winsock console application to Windows subsystem - stack overflow

Hey there wonderful community!
I'm back with a question regarding a console server application I've made with winsock. It's finally reaching a stage where I would need a to add a GUI, and to do so, I need it to be using the Windows subsystem.
And so I started the migration.
Yet I'm hitting a stack overflow somewhere in my application, and for the life of me I can't figure out where. Perhaps it has to do with WIN being a non-blocking subsystem (hope I used my vocab correctly).
Anyway, I hope to enlist you all as helpers. Many thanks :)
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <conio.h>
// Need to link with Ws2_32.lib
#pragma comment (lib, "Ws2_32.lib")
// #pragma comment (lib, "Mswsock.lib")
int minitialize();
int msend(char msendbuf[512]);
char* mrecv(bool show);
int mshutdown();
void GoToXY(int column, int line);
int scroll(void);
int printm(char *inp);
int printm(char *inp, DWORD color);
int mexit();
char *vir = "true";
int clientnumber=0;
int currentclient=0;
int lastclient=0;
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "10150"
struct _client
{
bool con;
sockaddr_in addr; //Client info like ip address
SOCKET cs; //Client socket
fd_set set; //used to check if there is data in the socket
std::string ip;
std::string name;
int i; //any piece of additional info
} client[100];
WSADATA wsaData;
int iResult;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET ClientSocket = INVALID_SOCKET;
struct addrinfo *result = NULL;
struct addrinfo hints;
int iSendResult;
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;
DWORD WINAPI recvfunc(LPVOID randparam)
{
while (true) {
ClientSocket=client[currentclient].cs;
if (mrecv(true)=="1") {
client[currentclient].con=false;
ClientSocket=client[lastclient].cs;
break;
}
}
return 0;
}
DWORD WINAPI headerfunc(LPVOID randparam)
{
Sleep(500);
while (true) {
CONSOLE_SCREEN_BUFFER_INFO SBInfo;
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hOut, &SBInfo);
int xx = SBInfo.dwCursorPosition.X;
int yy = SBInfo.dwCursorPosition.Y;
GoToXY(0,0);
HANDLE hHeaderColor;
hHeaderColor = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hHeaderColor, FOREGROUND_GREEN);
std::cout<<"Server Started. Current Client:"<<currentclient<<" Clients connected: "<<clientnumber<<" ("<<xx<<","<<yy<<") "<<lastclient;
SetConsoleTextAttribute(hHeaderColor, 0 |
FOREGROUND_RED |
FOREGROUND_GREEN |
FOREGROUND_BLUE);
GoToXY(xx,yy);
Sleep(2000);
}
return 0;
}
DWORD WINAPI sendfunc(LPVOID randparam)
{
while (true) {
char mmessage[512];
std::cin.getline(mmessage, 512);
if (strlen(mmessage)<2) {
GoToXY(0,23);
sendfunc("1");
}
char msendbuf[512]="Server> ";
strcat(msendbuf,mmessage);
if (msend(msendbuf)==1) {
"Client must have disconnected. Please select a new client.";
sendfunc("1");
}
if ((strncmp(msendbuf,"Server> /",9)) != 0) {
printm(msendbuf,FOREGROUND_INTENSITY);
}
GoToXY(0,23);
for (int sp=0; sp<72; sp++) {
std::cout<<" ";
}
GoToXY(0,23);
}
return 0;
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
minitialize();
HANDLE hRecvThread;
HANDLE hSendThread;
HANDLE hHeaderThread;
DWORD dwRecvThreadId;
DWORD dwSendThreadId;
DWORD dwHeaderThreadId;
hHeaderThread = CreateThread(NULL,0,headerfunc,"1",0,&dwHeaderThreadId);
for (int mf=2; mf<25; mf++) {
std::cout<<"\n";
}
hSendThread = CreateThread(NULL,0,sendfunc,"1",0,&dwSendThreadId);
// Accept a client socket
for (int sock=1; sock<100; sock++) {
ClientSocket = accept(ListenSocket, NULL, NULL);
char sockprint[80];
char sockchar[4];
itoa(sock,sockchar,10);
strcpy(sockprint,"Client ");
strcat(sockprint,sockchar);
strcat(sockprint," connected.");
printm(sockprint);
GoToXY(0,23);
if (ClientSocket == INVALID_SOCKET) {
printm("accept failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
client[sock].cs=ClientSocket;
client[sock].con=true;
lastclient=clientnumber;
clientnumber++;
currentclient=clientnumber;
hRecvThread = CreateThread(NULL,0,recvfunc,"1",0,&dwRecvThreadId);
}
// shutdown the connection since we're done
mshutdown();
std::cin.ignore();
return 0;
}
int printm(char *inp, DWORD color) {
HANDLE hOut;
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hOut,
color);
printm(inp);
SetConsoleTextAttribute(hOut, 0 |
FOREGROUND_RED |
FOREGROUND_GREEN |
FOREGROUND_BLUE);
return 0;
}
int printm(char *inp) {
CONSOLE_SCREEN_BUFFER_INFO SBInfo;
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hOut, &SBInfo);
int xx = SBInfo.dwCursorPosition.X;
int yy = SBInfo.dwCursorPosition.Y;
GoToXY(0,22);
std::cout<<inp<<"\n";
scroll();
GoToXY(xx,yy);
return 1;
}
int msend(char msendbuf[512]) // Send a message
{
if (strncmp(msendbuf,"Server> /exit",(strlen(msendbuf))) == 0) {
mexit();
}
if (strncmp(msendbuf,"Server> /set_client",19) == 0) {
int nm=atoi(&msendbuf[20]);
currentclient=nm;
ClientSocket=client[nm].cs;
char sockchar[4];
itoa(ClientSocket,sockchar,10);
char sockprint[80];
strcpy(sockprint,"New Socket: ");
strcat(sockprint,sockchar);
printm(sockprint);
char clientprint[80];
strcpy(clientprint,"Client: ");
strcat(clientprint,&msendbuf[20]);
printm(clientprint);
}
if (strncmp(msendbuf,"Server> /list_clients",(strlen(msendbuf))) == 0) {
printm("Clients:",FOREGROUND_RED);
for (int cm=1; cm < 100; cm++) {
int cn=client[cm].cs;
if (cn>0) {
char cli[80];
char cmchar[4];
char cnchar[80];
itoa(cn,cnchar,10);
itoa(cm,cmchar,10);
strcpy(cli,cmchar);
strcat(cli," ");
strcat(cli,cnchar);
strcat(cli," ");
strcat(cli,client[cm].ip.c_str());
strcat(cli," ");
strcat(cli,client[cm].name.c_str());
printm(cli,FOREGROUND_RED);
}
else {
break;
}
}
}
if (strncmp(msendbuf,"Server> /test",(strlen(msendbuf))) == 0) {
char ipcon[500];
*ipcon=(system("ipconfig"));
}
if (strncmp(msendbuf,"Server> /help",(strlen(msendbuf))) == 0) {
printm("Type /help for help or:");
printm("/set_client [client number]");
printm("/list_clients");
}
int iResult3 = send( ClientSocket, msendbuf, 512, 0 );
if (iResult3 == SOCKET_ERROR) {
printm("send failed with error: %d\n", WSAGetLastError());
return 1;
}
}
char* mrecv(bool show) //Recieve a message
{
int iResult2 = recv(ClientSocket, recvbuf, 512, 0);
if (iResult2 > 0) {
if ((strncmp(recvbuf,"/",1)) != 0) {
printm(recvbuf);
}
if (strncmp(recvbuf,"/ip",3) == 0) {
client[clientnumber].ip=&recvbuf[4];
char prin[80];
strcpy(prin,"client[clientnumber].ip: ");
strcat(prin,client[clientnumber].ip.c_str());
printm(prin,FOREGROUND_BLUE);
}
if (strncmp(recvbuf,"/name",5) == 0) {
client[clientnumber].name=&recvbuf[6];
char prin2[80];
strcpy(prin2,"client[clientnumber].name: ");
strcat(prin2,client[clientnumber].name.c_str());
printm(prin2,FOREGROUND_GREEN | FOREGROUND_BLUE);
}
if (strncmp(recvbuf,"/alert",5) == 0) {
char *message=&recvbuf[7];
char prin2[80];
strcpy(prin2,client[clientnumber].name.c_str());
strcat(prin2,": ");
strcat(prin2, message);
printm(prin2,FOREGROUND_RED);
}
if (strncmp(recvbuf,"Client> /alert",14) == 0) {
char *message=&recvbuf[15];
char prin2[80];
strcpy(prin2,client[clientnumber].name.c_str());
strcat(prin2,": ");
strcat(prin2, message);
printm(prin2,FOREGROUND_RED);
}
}
else if (iResult2 == 0) {
printf("Connection closing...\n");
closesocket(ClientSocket);
WSACleanup();
return "1";
}
else {
printm("recv failed with error: %d\n", WSAGetLastError());
printm("Client must have disconnected. Please select a new client.");
return "1";
}
return recvbuf;
}
int minitialize() //initialize the winsock server
{
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printm("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Resolve the server address and port
iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if ( iResult != 0 ) {
printm("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Create a SOCKET for connecting to server
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET) {
printm("socket failed with error: %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
// Setup the TCP listening socket
iResult = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR) {
printm("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
return 1;
}
freeaddrinfo(result);
iResult = listen(ListenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR) {
printm("listen failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
unsigned long b=1;
ioctlsocket(ClientSocket,FIONBIO,&b);
}
int mshutdown() //shutdown the server
{
iResult = shutdown(ClientSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printm("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
// cleanup
closesocket(ClientSocket);
WSACleanup();
return 0;
}
void GoToXY(int column, int line)
{
// Create a COORD structure and fill in its members.
// This specifies the new position of the cursor that we will set.
COORD coord;
coord.X = column;
coord.Y = line;
// Obtain a handle to the console screen buffer.
// (You're just using the standard console, so you can use STD_OUTPUT_HANDLE
// in conjunction with the GetStdHandle() to retrieve the handle.)
// Note that because it is a standard handle, we don't need to close it.
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
// Finally, call the SetConsoleCursorPosition function.
if (!SetConsoleCursorPosition(hConsole, coord))
{
// Uh-oh! The function call failed, so you need to handle the error.
// You can call GetLastError() to get a more specific error code.
// ...
return;
}
}
int scroll( void )
{
HANDLE hStdout;
CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
SMALL_RECT srctScrollRect, srctClipRect;
CHAR_INFO chiFill;
COORD coordDest;
hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
if (hStdout == INVALID_HANDLE_VALUE)
{
printf("GetStdHandle failed with %d\n", GetLastError());
return 1;
}
// Get the screen buffer size.
if (!GetConsoleScreenBufferInfo(hStdout, &csbiInfo))
{
printf("GetConsoleScreenBufferInfo failed %d\n", GetLastError());
return 1;
}
// The scrolling rectangle
srctScrollRect.Top = 1;
srctScrollRect.Bottom = 22;
srctScrollRect.Left = 0;
srctScrollRect.Right = csbiInfo.dwSize.X - 1;
// The destination for the scroll rectangle is one row up.
coordDest.X = 0;
coordDest.Y = 0;
// The clipping rectangle
srctClipRect.Top = 2;
srctClipRect.Bottom = 22;
srctClipRect.Left = 0;
srctClipRect.Right = csbiInfo.dwSize.X - 1;
// Fill the bottom row with blanks.
chiFill.Attributes = FOREGROUND_RED;
chiFill.Char.AsciiChar = (char)' ';
// Scroll up one line.
if(!ScrollConsoleScreenBuffer(
hStdout, // screen buffer handle
&srctScrollRect, // scrolling rectangle
&srctClipRect, // clipping rectangle
coordDest, // top left destination cell
&chiFill)) // fill character and color
{
printf("ScrollConsoleScreenBuffer failed %d\n", GetLastError());
return 1;
}
return 0;
}
int mexit()
{
msend("/server_closed");
mshutdown();
exit(0);
}
Turns out it was the recursive calling in my "sendfunc" thread that tripped me up.
Specifically,
if (msend(msendbuf)==1) {
"Client must have disconnected. Please select a new client.";
sendfunc("1");
}
Because I continued to call "sendfunc" from itself, it caused the stack overflow.
So, for anyone else having these problems, watch for overkill recursive function calls.
I simply removed my sending function and I was good to go.

sqlite3_prepare error c++ cygwin under x64 TDM

I'm compiling a example application which uses the sqlite3 using the source
code on my windows x64 machine.
#include "sqlite3.h"
#include <stdio.h>
#include <string.h>
#include <windows.h>
int main(int argc,char **argv)
{
sqlite3 *db;
sqlite3_stmt * pSqllite3_stmt=NULL;
char *zErrMsg=0;
int rc;
// create a new database //
rc =sqlite3_open( ".\\sql_lite3.db" ,&db);
if(rc!=SQLITE_OK|| db == NULL)
{
MessageBox(NULL,TEXT("can't open the database") , TEXT("sql_lite example"), MB_OK);
exit(0);
}
// create a table called string_index //
char * create_query = "create table string_table (index INT ,string TEXT);" ;
rc = sqlite3_prepare_v2( db , create_query, -1, &pSqllite3_stmt,NULL);
if (rc != SQLITE_OK ) {
// if an error occurred //
char error_code[128];
sprintf(error_code," Error Code is %d" ,rc);
MessageBox( NULL, error_code,TEXT("sql_lite example"), MB_OK);
exit(0);
}
// step the create query //
rc = sqlite3_step(pSqllite3_stmt);
if(SQLITE_OK != rc)
{
MessageBox(NULL,TEXT("Create step have failed "),TEXT("sql lite example"),MB_OK);
exit(0);
}
// insert records to the database //
char *insert_query = new char [ 1024];
int i;
sqlite3_stmt * insert_stmt ;
char * insert_string ="This is the insert String";
for (i=1; i<= 10;i++){
sprintf( insert_query,"INSERT INTO string_table(index,string) VALUES(%d,?1);" , \
i);
// execute the insert query //
rc = sqlite3_prepare_v2(db , insert_query,strlen(insert_query), &insert_stmt,NULL);
if(rc!= SQLITE_OK)
{
MessageBox(NULL,TEXT("INSERT INTO have been failed"), TEXT("SQLITE EXAMPLE"),MB_OK);
exit(0);
}
// bind the string //
rc =sqlite3_bind_text(insert_stmt,1,insert_string,sizeof(insert_string),SQLITE_TRANSIENT);
if(rc != SQLITE_OK && rc != SQLITE_DONE)
{
MessageBox(NULL,TEXT("bind failed"),TEXT("SQLITE EXAMPLE"), MB_OK);
exit(0);
}
// call step //
rc = sqlite3_step(insert_stmt);
if( rc != SQLITE_OK)
{
MessageBox(NULL,TEXT("Insertion step failed "),TEXT("SQLITE EXAMPLE"),MB_OK);
exit(0);
}
// finalize the insert query //
sqlite3_finalize(insert_stmt);
}
// now we are going to execute the search query //
char * search_query = "SELECT * FROM string_table WHERE index=10";
sqlite3_stmt * search_stmt ;
rc = sqlite3_prepare_v2(db,search_query,sizeof(search_query),&search_stmt,NULL);
if( SQLITE_OK== rc)
{
while( SQLITE_ROW == sqlite3_step(search_stmt ) )
{
// print the record //
const int index_value= sqlite3_column_int(search_stmt,1);
const unsigned char * string_value = sqlite3_column_text(search_stmt,2);
printf( "index :%d and string:%s ",index_value,string_value );
}
}else{
MessageBox(NULL,TEXT("Searching query sqlite3 have been failed"),TEXT("SQLITE example"), MB_OK);
exit(0);
}
// fnalize the search statement //
sqlite3_finalize(search_stmt);
// don't forget to close the connection //
sqlite3_close(db);
return 0;
}
But when I trying to create a table it always gives me the error code 1.
Which means , the bellow code fails.
// create a table called string_index //
char * create_query = "create table string_table (index INT ,string TEXT);" ;
rc = sqlite3_prepare_v2( db , create_query, -1, &pSqllite3_stmt,NULL);
if (rc != SQLITE_OK ) {
// if an error occurred //
char error_code[128];
sprintf(error_code," Error Code is %d" ,rc);
MessageBox( NULL, error_code,TEXT("sql_lite example"), MB_OK);
exit(0);
}
Why is that ? How could I overcome this issue?
Any suggestions, or improvements?
--Thanks in advance--
To show a useful error message, use sqlite3_errmsg:
MessageBox(0, sqlite3_errmsg(db), NULL, 0);
As for your SQL command: index is a keyword, so you have to quote it whenever you use it:
CREATE TABLE string_table("index" INT, string TEXT);
It might be easier to use another column name.

ConnectEx requires the socket to be "initially bound", but to what?

The ConnectEx function requires an "unconnected, previously bound socket". Indeed, if I omit the bind step in my example (see below), ConnectEx fails with WSAEINVAL.
Here's my current understanding: before calling ConnectEx, bind the socket to INADDR_ANY and port 0 (unless it is already bound):
struct sockaddr_in addr;
ZeroMemory(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = 0;
rc = bind(sock, (SOCKADDR*) &addr, sizeof(addr));
if (rc != 0) { ... bind failed; call WSAGetLastError to see why ... }
Or for an IPv6 socket:
struct sockaddr_in6 addr;
ZeroMemory(&addr, sizeof(addr));
addr.sin6_family = AF_INET6;
addr.sin6_addr = in6addr_any;
addr.sin6_port = 0;
rc = bind(sock, (SOCKADDR*) &addr, sizeof(addr));
if (rc != 0) { ... bind failed; call WSAGetLastError to see why ... }
This lets the operating system assign a local address to our socket (as opposed to the remote address we are connecting to). connect does this step automatically, but ConnectEx does not.
My questions are:
Is my assessment correct?
Is there a way to do this automatic bind that is agnostic to the address family, or will I have to handle each of AF_INET, AF_INET6, AF_BTH (Bluetooth), etc. manually?
Working ConnectEx example (also on Gist: https://gist.github.com/4158972):
#include <stdio.h>
#include <WinSock2.h>
#include <MSWSock.h>
#include <WS2tcpip.h>
#pragma comment(lib, "Ws2_32.lib")
struct mswsock_s {
LPFN_CONNECTEX ConnectEx;
} mswsock;
static BOOL load_mswsock(void)
{
SOCKET sock;
DWORD dwBytes;
int rc;
/* Dummy socket needed for WSAIoctl */
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET)
return FALSE;
{
GUID guid = WSAID_CONNECTEX;
rc = WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER,
&guid, sizeof(guid),
&mswsock.ConnectEx, sizeof(mswsock.ConnectEx),
&dwBytes, NULL, NULL);
if (rc != 0)
return FALSE;
}
rc = closesocket(sock);
if (rc != 0)
return FALSE;
return TRUE;
}
int main(int argc, char *argv[])
{
int rc;
BOOL ok;
WSADATA wsaData;
SOCKET sock;
rc = WSAStartup(MAKEWORD(2,2), &wsaData);
if (rc != 0) {
printf("WSAStartup failed: %d\n", rc);
return 1;
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
printf("Your computer is from the wrong millenium.\n");
WSACleanup();
return 1;
}
if (!load_mswsock()) {
printf("Error loading mswsock functions: %d\n", WSAGetLastError());
return 1;
}
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET) {
printf("socket: %d\n", WSAGetLastError());
return 1;
}
/* ConnectEx requires the socket to be initially bound. */
{
struct sockaddr_in addr;
ZeroMemory(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = 0;
rc = bind(sock, (SOCKADDR*) &addr, sizeof(addr));
if (rc != 0) {
printf("bind failed: %d\n", WSAGetLastError());
return 1;
}
}
/* Issue ConnectEx and wait for the operation to complete. */
{
OVERLAPPED ol;
ZeroMemory(&ol, sizeof(ol));
sockaddr_in addr;
ZeroMemory(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("173.194.37.36"); // google.com
addr.sin_port = htons(80);
ok = mswsock.ConnectEx(sock, (SOCKADDR*) &addr, sizeof(addr), NULL, 0, NULL, &ol);
if (ok) {
printf("ConnectEx succeeded immediately\n");
} else if (WSAGetLastError() == ERROR_IO_PENDING) {
printf("ConnectEx pending\n");
DWORD numBytes;
ok = GetOverlappedResult((HANDLE) sock, &ol, &numBytes, TRUE);
if (ok)
printf("ConnectEx succeeded\n");
else
printf("ConnectEx failed: %d\n", WSAGetLastError());
} else {
printf("ConnectEx failed: %d\n", WSAGetLastError());
return 1;
}
}
/* Make the socket more well-behaved. */
rc = setsockopt(sock, SOL_SOCKET, SO_UPDATE_CONNECT_CONTEXT, NULL, 0);
if (rc != 0) {
printf("SO_UPDATE_CONNECT_CONTEXT failed: %d\n", WSAGetLastError());
return 1;
}
/* This will fail if SO_UPDATE_CONNECT_CONTEXT was not performed. */
rc = shutdown(sock, SD_BOTH);
if (rc != 0) {
printf("shutdown failed: %d\n", WSAGetLastError());
return 1;
}
printf("Done\n");
return 0;
}
connect does this step automatically, but ConnectEx does not.
Correct.
Is my assessment correct?
Yes.
Is there a way to do this automatic bind that is agnostic to the address family, or will I have to handle each of AF_INET, AF_INET6, AF_BTH (Bluetooth), etc. manually?
I believe that INADDR_ANY is a bunch of zeros in all address families, so you could just try using the memset() and omitting the assignment to addr.sin_addr.s_addr completely. Whether this is kosher, portable, politically correct etc. is another question into which I will not enter.
It seems pretty curious that Microsoft didn't manage to have ConnectEx() call bind() internally, considering that saving system calls is the motivation for its existence, and also considering that most programs never bind an outbound socket at all.
It is possible to get the bind address for ConnectEx in an address family independent way.
Solution 1
Call getaddrinfo with the following options:
pServiceName = "0"
hints.ai_flags = AI_PASSIVE
hints.ai_family = address family of the socket
Then use the first result of the returned address list.
To get the address family of the socket you can use getsockopt with SO_PROTOCOL_INFOW.
Solution 2
Use SOCKADDR_STORAGE for the address structure and call INETADDR_SETANY which is defined in MSTcpIP.h. It supports AF_INET and AF_INET6.

Resources