I have an application made in c ++ that acts as a server. Gameserver.exe
The problem is that they manage to attack gameserver.exe with http flood connections, for example http://ip:port
The attacks are sent from an application called "railgun"
How can I block or prevent these http connections?
Currently I use an anti flood in the gameserver.exe application which is basically this.
int gObjGetIPIndex(char* IpAddress)
{
int Ret = -1;
for (int x = 0; x < LastIPList; x++)
{
if (IPList[x][0] == IpAddress[0])
{
if (strcmp(IPList[x], IpAddress) == 0)
{
return x;
break;
}
}
}
Ret = LastIPList;
sprintf(IPList[LastIPList], "%s", IpAddress);
LastIPList++;
if (LastIPList >= 2000)LastIPList = 0;
return Ret;
}
short gObjAdd(SOCKET socket, char* IpAddress, int aIndex) // OK stdafx.h ?
{
if (OBJECT_RANGE(aIndex) == 0)
{
return -1;
}
if (gObj[aIndex].Connected != OBJECT_OFFLINE)
{
return -1;
}
//========================================
// Anti Flood Fix 13/08/2020
//========================================
if (gServerInfo.m_EnableAntiflood == 1)
{
int IPIndex = gObjGetIPIndex(IpAddress);
DWORD CurTick = GetTickCount();
if ((CurTick - LastConnect[IPIndex]) < 1000)
{
LastConnect[IPIndex] = CurTick;
LogAdd(LOG_RED, "[AntiFlood][%d] BlockAttack (%s)", aIndex, IpAddress);
return -1;
}
LastConnect[IPIndex] = CurTick;
}
Thanks for your time.
Related
The image linked above is the HTML that browser shows. Every time when I press a link, the server cannot accept the correct HTTP information from the browser. Below is my code related to communicating through HTTP.
char buf[2048];
http_handle hh(connfd, buf, 2048);
read(connfd, buf, 2048);
hh.handle_http_request(&hh);
hh.response_http_request(&hh); //the first two function works
read(connfd, buf, 2048); //this returns 0
hh.handle_http_request(&hh);
hh.response_http_request(&hh);
Below is the implementation of handle_http_requestandresponse_http_request:
void* http_handle::handle_http_request(void* arg) {
http_handle* hp = (http_handle*)arg;
hp->_handle_http_request();
return hp;
}
void http_handle::_handle_http_request() {
int i, j;
for (i = 0; this->buf[i] != ' '; i++)
method[i] = this->buf[i];
method[i] = 0;
for (j = 0, ++i; this->buf[i] != ' '; i++, j++)
url[j] = this->buf[i];
url[j] = 0;
//method stores http operations like GET and POST
//url stores the url resource in the http start line
if (!strcasecmp(method, "GET")) {
//...
}
if (!strcasecmp(method, "POST")) {
//...
}
}
void* http_handle::response_http_request(void* arg) {
http_handle* hp = (http_handle*)arg;
hp->_response_http_request();
return hp;
}
void http_handle::_response_http_request() {
if (strcasecmp(method, "GET") && strcasecmp(method, "POST")) {
unimpelented();
return;
}
if (!strcasecmp(method, "GET")) {
if (strcmp(url, "/") == 0) {
char tmp_path[256];
http_handle::path = getcwd(tmp_path, 256);
trans_dir("src");
return;
}
std::string filepath = http_handle::path + "/" + url;
struct stat filestat;
if ((stat(filepath.c_str(), &filestat)) != 0) {
perror("_response_http_request stat error");
exit(1);
}
switch (filestat.st_mode & S_IFMT) {
case S_IFREG:
trans_file(filepath);
break;
case S_IFDIR:
trans_dir(filepath);
break;
default:
break;
}
return;
}
if (!strcasecmp(method, "POST")) { //to be implemented
return;
}
}
read() returns 0 when EOF is reached, ie when the peer has closed the TCP connection on its end.
The data you have shown is not larger than your buffer, so the first read() receives all of the data, and there is nothing left for the second read() because the server closed the connection after sending the data.
I'm developing a mmorpg with iocp sockets.When im testing with my client simulator , after 70-80 connection , writing operation at socket worker thread slowing down than users get lagged.
This is my worker thread ;
typedef void(*OperationHandler)(Socket * s, uint32 len);
void HandleReadComplete(Socket * s, uint32 len);
void HandleWriteComplete(Socket * s, uint32 len);
void HandleShutdown(Socket * s, uint32 len);
static OperationHandler ophandlers[] =
{
&HandleReadComplete,
&HandleWriteComplete,
&HandleShutdown
};
uint32 THREADCALL SocketMgr::SocketWorkerThread(void * lpParam){
SocketMgr *socketMgr = (SocketMgr *)lpParam;
HANDLE cp = socketMgr->GetCompletionPort();
DWORD len;
Socket * s = nullptr;
OverlappedStruct * ov = nullptr;
LPOVERLAPPED ol_ptr;
while (socketMgr->m_bWorkerThreadsActive)
{
if (!GetQueuedCompletionStatus(cp, &len, (LPDWORD)&s, &ol_ptr, INFINITE))
{
if (s != nullptr)
s->Disconnect();
continue;
}
ov = CONTAINING_RECORD(ol_ptr, OverlappedStruct, m_overlap);
if (ov->m_event == SOCKET_IO_THREAD_SHUTDOWN)
{
delete ov;
return 0;
}
if (ov->m_event < NUM_SOCKET_IO_EVENTS)
ophandlers[ov->m_event](s, len);
}
return 0;}
This is Write Complete event handler;
void HandleWriteComplete(Socket * s, uint32 len)
{
if (s->IsDeleted()) {
return;
}
s->m_writeEvent.Unmark();
s->BurstBegin(); // Lock
s->GetWriteBuffer().Remove(len);
TRACE("SOCK = %d removed = %d",s->GetFd(),len);
if (s->GetWriteBuffer().GetContiguousBytes() > 0) {
s->WriteCallback();
}
else {
s->DecSendLock();
}
s->BurstEnd(); // Unlock
}
WriteCallBack function ;
void Socket::WriteCallback()
{
if (IsDeleted() || !IsConnected()) {
return;
}
// We don't want any writes going on while this is happening.
Guard lock(m_writeMutex);
if(writeBuffer.GetContiguousBytes())
{
DWORD w_length = 0;
DWORD flags = 0;
// attempt to push all the data out in a non-blocking fashion.
WSABUF buf;
buf.len = (ULONG)writeBuffer.GetContiguousBytes();
buf.buf = (char*)writeBuffer.GetBufferStart();
m_writeEvent.Mark();
m_writeEvent.Reset(SOCKET_IO_EVENT_WRITE_END);
TRACE("\n SOCK = %d aslında giden = %X THREADID = %d", GetFd(), buf.buf[4],GetCurrentThreadId());
int r = WSASend(m_fd, &buf, 1, &w_length, flags, &m_writeEvent.m_overlap, 0);
if (r == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING)
{
m_writeEvent.Unmark();
DecSendLock();
Disconnect();
}
}
else
{
// Write operation is completed.
DecSendLock();
}
}
this is stuffs about mutexes ;
public:
/* Atomic wrapper functions for increasing read/write locks */
INLINE void IncSendLock() { Guard lock(m_writeMutex); ++m_writeLock; }
INLINE void DecSendLock() { Guard lock(m_writeMutex);
--m_writeLock; }
INLINE bool HasSendLock() {Guard lock(m_writeMutex); return (m_writeLock != 0); }
INLINE bool AcquireSendLock()
{
Guard lock(m_writeMutex);
if (m_writeLock != 0)
return false;
++m_writeLock;
return true;
}
private:
// Write lock, stops multiple write events from being posted.
uint32 m_writeLock;
std::recursive_mutex m_writeLockMutex;
This is read event handler;
void HandleReadComplete(Socket * s, uint32 len)
{
if (s->IsDeleted())
return;
s->m_readEvent.Unmark();
if (len)
{
s->GetReadBuffer().IncrementWritten(len);
s->OnRead();
s->SetupReadEvent();
}
else
{
// s->Delete(); // Queue deletion.
s->Disconnect();
}
}
OnRead function ;
void KOSocket::OnRead()
{
Packet pkt;
for (;;)
{
if (m_remaining == 0)
{
if (GetReadBuffer().GetSize() < 5) {
//TRACE("pkt returnzzz GetFd %d", GetFd());
return; //check for opcode as well
}
uint16 header = 0;
GetReadBuffer().Read(&header, 2);
//printf("header : %X", header);//derle at k
if (header != 0x55AA)
{
TRACE("%s: Got packet without header 0x55AA, got 0x%X\n", GetRemoteIP().c_str(), header);
goto error_handler;
}
GetReadBuffer().Read(&m_remaining, 2);
if (m_remaining == 0)
{
TRACE("%s: Got packet without an opcode, this should never happen.\n", GetRemoteIP().c_str());
goto error_handler;
}
}
if (m_remaining > GetReadBuffer().GetAllocatedSize())
{
TRACE("%s: Packet received which was %u bytes in size, maximum of %u.\n", GetRemoteIP().c_str(), m_remaining, GetReadBuffer().GetAllocatedSize());
goto error_handler;
}
if (m_remaining > GetReadBuffer().GetSize())
{
if (m_readTries > 4)
{
TRACE("%s: packet fragmentation count is over 4, disconnecting as they're probably up to something bad\n", GetRemoteIP().c_str());
goto error_handler;
}
m_readTries++;
return;
}
uint8 *in_stream = new uint8[m_remaining];
m_readTries = 0;
GetReadBuffer().Read(in_stream, m_remaining);
uint16 footer = 0;
GetReadBuffer().Read(&footer, 2);
if (footer != 0xAA55
|| !DecryptPacket(in_stream, pkt))
{
TRACE("%s: Footer invalid (%X) or failed to decrypt.\n", GetRemoteIP().c_str(), footer);
delete [] in_stream;
goto error_handler;
}
delete [] in_stream;
// Update the time of the last (valid) response from the client.
m_lastResponse = UNIXTIME2;
//TRACE("pkt:%d GetFd %d", pkt.GetOpcode(), GetFd());
if (!HandlePacket(pkt))
{
TRACE("%s: Handler for packet %X returned false\n", GetRemoteIP().c_str(), pkt.GetOpcode());
#ifndef _DEBUG
goto error_handler;
#endif
}
m_remaining = 0;
}
//TRACE("pkt return11 GetFd %d", GetFd());
return;
error_handler:
Disconnect();
}
and this is how my server sends to packet to clients ;
BurstBegin();
//TRACE("\n SOCK = %d FREE SPACE = %d ",GetFd(),GetWriteBuffer().GetSpace()/*, GetWriteBuffer().m_writeLock*/);
if (GetWriteBuffer().GetSpace() < size_t(len + 6))
{
size_t freespace = GetWriteBuffer().GetSpace();
BurstEnd();
Disconnect();
return false;
}
TRACE("\n SOCK = %d gitmesi gereken paket = %X THREADID = %d", GetFd(), out_stream[0],GetCurrentThreadId());
r = BurstSend((const uint8*)"\xaa\x55", 2);
if (r) r = BurstSend((const uint8*)&len, 2);
if (r) r = BurstSend((const uint8*)out_stream, len);
if (r) r = BurstSend((const uint8*)"\x55\xaa", 2);
if (r) BurstPush();
BurstEnd();
The number of Worker threads according to processor number;
for(int i = 0; i < numberOfWorkerThreads; i++)
{
m_thread[i] = new Thread(SocketWorkerThread, this);
}
The server which i tested on it has Intel XEON E5-2630 v3 2.40 ghz (2 processor)
Can you guys help me about how can i improve performance ? For ex: when the client moves in the map per 1.5 second that sends to move packet to server and if it success server sends to every client in that region that move packet.
When client count increasing server starts to slow down to send back to packets to clients.My write buffer filling fully (it's capacity 16384 bytes) cause server couldn't send packets inside of the writebuffer.
I am trying to setup the Interactive Brokers API on Ubuntu (18.04). I have installed both the IB Gateway, which is used for communicating with exchanges, as well as other API software for developing trading algorithms in Java, C++, C# and Python. (Which you can find here). The API is written in both Java and C++, and as stated prior it offers support for both. However when attempting to compile an example from their source code there is an error in the EReader.cpp file. I have dealt with several other C++ errors in their code however this one I cannot figure out. Here is the code:
#include "StdAfx.h"
#include "shared_ptr.h"
#include "Contract.h"
#include "EDecoder.h"
#include "EMutex.h"
#include "EReader.h"
#include "EClientSocket.h"
#include "EPosixClientSocketPlatform.h"
#include "EReaderSignal.h"
#include "EMessage.h"
#include "DefaultEWrapper.h"
#define IN_BUF_SIZE_DEFAULT 8192
static DefaultEWrapper defaultWrapper;
EReader::EReader(EClientSocket *clientSocket, EReaderSignal *signal)
: processMsgsDecoder_(clientSocket->EClient::serverVersion(), clientSocket->getWrapper(), clientSocket) {
m_isAlive = true;
m_pClientSocket = clientSocket;
m_pEReaderSignal = signal;
m_needsWriteSelect = false;
m_nMaxBufSize = IN_BUF_SIZE_DEFAULT;
m_buf.reserve(IN_BUF_SIZE_DEFAULT);
}
EReader::~EReader(void) {
m_isAlive = false;
#if defined(IB_WIN32)
WaitForSingleObject(m_hReadThread, INFINITE);
#endif
}
void EReader::checkClient() {
m_needsWriteSelect = !m_pClientSocket->getTransport()-
isOutBufferEmpty();
}
void EReader::start() {
#if defined(IB_POSIX)
pthread_t thread;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create( &thread, &attr, readToQueueThread, this );
pthread_attr_destroy(&attr);
#elif defined(IB_WIN32)
m_hReadThread = CreateThread(0, 0, readToQueueThread, this, 0, 0);
#else
# error "Not implemented on this platform"
#endif
}
#if defined(IB_POSIX)
void * EReader::readToQueueThread(void * lpParam)
#elif defined(IB_WIN32)
DWORD WINAPI EReader::readToQueueThread(LPVOID lpParam)
#else
# error "Not implemented on this platform"
#endif
{
EReader *pThis = reinterpret_cast<EReader *>(lpParam);
pThis->readToQueue();
return 0;
}
void EReader::readToQueue() {
EMessage *msg = 0;
while (m_isAlive) {
if (m_buf.size() == 0 && !processNonBlockingSelect() && m_pClientSocket->isSocketOK())
continue;
if (!putMessageToQueue())
break;
}
m_pClientSocket->handleSocketError();
m_pEReaderSignal->issueSignal(); //letting client know that socket was closed
}
bool EReader::putMessageToQueue() {
EMessage *msg = 0;
if (m_pClientSocket->isSocketOK())
msg = readSingleMsg();
if (msg == 0)
return false;
m_csMsgQueue.Enter();
m_msgQueue.push_back(ibapi::shared_ptr<EMessage>(msg));
m_csMsgQueue.Leave();
m_pEReaderSignal->issueSignal();
return true;
}
bool EReader::processNonBlockingSelect() {
fd_set readSet, writeSet, errorSet;
struct timeval tval;
tval.tv_usec = 100 * 1000; //100 ms
tval.tv_sec = 0;
if( m_pClientSocket->fd() >= 0 ) {
FD_ZERO( &readSet);
errorSet = writeSet = readSet;
FD_SET( m_pClientSocket->fd(), &readSet);
if (m_needsWriteSelect)
FD_SET( m_pClientSocket->fd(), &writeSet);
FD_SET( m_pClientSocket->fd(), &errorSet);
int ret = select( m_pClientSocket->fd() + 1, &readSet, &writeSet, &errorSet, &tval);
if( ret == 0) { // timeout
return false;
}
if( ret < 0) { // error
m_pClientSocket->eDisconnect();
return false;
}
if( m_pClientSocket->fd() < 0)
return false;
if( FD_ISSET( m_pClientSocket->fd(), &errorSet)) {
// error on socket
m_pClientSocket->onError();
}
if( m_pClientSocket->fd() < 0)
return false;
if( FD_ISSET( m_pClientSocket->fd(), &writeSet)) {
// socket is ready for writing
onSend();
}
if( m_pClientSocket->fd() < 0)
return false;
if( FD_ISSET( m_pClientSocket->fd(), &readSet)) {
// socket is ready for reading
onReceive();
}
return true;
}
return false;
}
void EReader::onSend() {
m_pEReaderSignal->issueSignal();
}
void EReader::onReceive() {
int nOffset = m_buf.size();
m_buf.resize(m_nMaxBufSize);
int nRes = m_pClientSocket->receive(m_buf.data() + nOffset, m_buf.size() - nOffset);
if (nRes <= 0)
return;
m_buf.resize(nRes + nOffset);
}
bool EReader::bufferedRead(char *buf, int size) {
while (size > 0) {
while (m_buf.size() < size && m_buf.size() < m_nMaxBufSize)
if (!processNonBlockingSelect() && !m_pClientSocket->isSocketOK())
return false;
int nBytes = (std::min<unsigned int>)(m_nMaxBufSize, size);
std::copy(m_buf.begin(), m_buf.begin() + nBytes, buf);
std::copy(m_buf.begin() + nBytes, m_buf.end(), m_buf.begin());
m_buf.resize(m_buf.size() - nBytes);
size -= nBytes;
buf += nBytes;
}
return true;
}
EMessage * EReader::readSingleMsg() {
if (m_pClientSocket->usingV100Plus()) {
int msgSize;
if (!bufferedRead((char *)&msgSize, sizeof(msgSize)))
return 0;
msgSize = htonl(msgSize);
if (msgSize <= 0 || msgSize > MAX_MSG_LEN)
return 0;
std::vector<char> buf = std::vector<char>(msgSize);
if (!bufferedRead(buf.data(), buf.size()))
return 0;
return new EMessage(buf);
}
else {
const char *pBegin = 0;
const char *pEnd = 0;
int msgSize = 0;
while (msgSize == 0)
{
if (m_buf.size() >= m_nMaxBufSize * 3/4)
m_nMaxBufSize *= 2;
if (!processNonBlockingSelect() && !m_pClientSocket->isSocketOK())
return 0;
pBegin = m_buf.data();
pEnd = pBegin + m_buf.size();
msgSize = EDecoder(m_pClientSocket->EClient::serverVersion(), &defaultWrapper).parseAndProcessMsg(pBegin, pEnd);
}
std::vector<char> msgData(msgSize);
if (!bufferedRead(msgData.data(), msgSize))
return 0;
if (m_buf.size() < IN_BUF_SIZE_DEFAULT && m_buf.capacity() > IN_BUF_SIZE_DEFAULT)
{
m_buf.resize(m_nMaxBufSize = IN_BUF_SIZE_DEFAULT);
m_buf.shrink_to_fit();
}
EMessage * msg = new EMessage(msgData);
return msg;
}
}
ibapi::shared_ptr<EMessage> EReader::getMsg(void) {
m_csMsgQueue.Enter();
if (m_msgQueue.size() == 0) {
m_csMsgQueue.Leave();
return ibapi::shared_ptr<EMessage>();
}
ibapi::shared_ptr<EMessage> msg = m_msgQueue.front();
m_msgQueue.pop_front();
m_csMsgQueue.Leave();
return msg;
}
void EReader::processMsgs(void) {
m_pClientSocket->onSend();
checkClient();
ibapi::shared_ptr<EMessage> msg = getMsg();
if (!msg.get())
return;
const char *pBegin = msg->begin();
while (processMsgsDecoder_.parseAndProcessMsg(pBegin, msg->end()) > 0)
{
msg = getMsg();
if (!msg.get())
break;
pBegin = msg->begin();
}
}
The error I get it is the following:
error: 'min' was not declared in this scope int nBytes =
min(m_nMaxBuffSize, size);
I have had to do other things such as editing other source code and makefiles, I am stuck here. Any insight would be appreciated.
In my version 973 source at that line I have
int nBytes = (std::min<unsigned int>)(m_nMaxBufSize, size);
Make sure you are using the latest version. The problem may be an example of what happens here Why is "using namespace std" considered bad practice?
I'm currently working on a project that involves bringing information back from devices plugged in via true usb. To solve this, I'm attempting to use libusb in my C++ project. I'm on Windows 10, using C++ and QT Creator with QT version 5.2.1. I can get the vendor ID and product ID of my device with .idVendor and idProduct. However, my serial number is returning as 0 with .iSerialNumber. I'll post my code below and hopefully someone can help me figure out what I'm missing or suggest another library for me to try. Thanks!
bool CPumpFinder::pollTrueUSB(boolean &deviceFound, Device &newDevice)
{
boolean usbFound = FALSE;
boolean accuCheckFound = FALSE;
AccuGuideCom *acc = new AccuGuideCom();
libusb_device **devs; //pointer to pointer of device, used to retrieve a list of devices
libusb_context *ctx = NULL; //a libusb session
int r; //for return values
ssize_t cnt; //holding number of devices in list
r = libusb_init(&ctx); //initialize a library session
if(r < 0) {
return 1;
}
libusb_set_debug(ctx, 3); //set verbosity level to 3, as suggested in the documentation
cnt = libusb_get_device_list(ctx, &devs); //get the list of devices
if(cnt < 0) {
}
ssize_t i; //for iterating through the list
for(i = 0; i < cnt; i++) {
printdev(devs[i], usbFound, accuCheckFound); //print specs of this device
if(usbFound == TRUE)
{
if(accuCheckFound == TRUE)
{
newDevice.displayName = "ACCU-CHEK GUIDE";
newDevice.type = DEVICE_ACCUCHECKGUIDE;
newDevice.vendorID = accuVID;
newDevice.productID = accuPID;
newDevice.serial = accuSerial;
}
deviceFound = TRUE;
break;
}
}
libusb_free_device_list(devs, 1); //free the list, unref the devices in it
libusb_exit(ctx); //close the session
return deviceFound;
}
boolean CPumpFinder::printdev(libusb_device *dev, boolean &usbFound, boolean
&accuChekFound) {
libusb_device_descriptor desc;
int r = libusb_get_device_descriptor(dev, &desc);
if (r < 0) {
return usbFound;
}
uint16 vID = (uint16)desc.idVendor;
uint16 pID = (uint16)desc.idProduct; //desc.iSerialNumber
//#define ACCUCHEK_GUIDE_VENDORID (uint16)0x173A
//#define ACCUCHEK_GUIDE_PRODUCTID (uint16)0x21D5
if((vID == 5946) & (pID == 8661))
{
accuPID = pID;
accuVID = vID;
//Do serial?
accuSerial = "Test";
write_text_to_log_file("we did it");
accuChekFound = TRUE;
usbFound = TRUE;
}
if(usbFound == TRUE)
{
libusb_config_descriptor *config;
libusb_get_config_descriptor(dev, 0, &config);
const libusb_interface *inter;
const libusb_interface_descriptor *interdesc;
const libusb_endpoint_descriptor *epdesc;
for(int i=0; i<(int)config->bNumInterfaces; i++) {
inter = &config->interface[i];
for(int j=0; j<inter->num_altsetting; j++) {
interdesc = &inter->altsetting[j];
for(int k=0; k<(int)interdesc->bNumEndpoints; k++) {
epdesc = &interdesc->endpoint[k];
}
}
}
libusb_free_config_descriptor(config);
if(accuChekFound == TRUE)
{
return accuChekFound;
}
return usbFound;
}
return usbFound;
}
I have a matrix relay with a nanopi fire (like rasperry pi). I connected this relay to my device and want to change gpio value.(my device has multi gpio pin. first I should create gpio(echo 95 > /sys/class/gpio/export) and then change direction folder "out" (echo "out" > /sys/class/gpio/gpio95/direction) and with changing value the relay should turn on and off.)
this is my code:
bool GPIOClass::ChangeValue(QString IO, QString port)
{
QString gpio;
QString comand;
// comand=" echo ";
// comand.append(QIO);
// comand.append(" > ");
// gpio=config->GpioFromPort(port);
// if(gpio.length()==0)
// return false;
// //IO should be 1 or 0
QString src=IdenGPIOSrc(gpio);//src is /sys/class/gpio/gpio95
src.append("/value");
// comand.append(src);
// qDebug()<<port<<gpio<<"with src:"
// <<src <<"with command:"<<comand;
// system(comand.toStdString().c_str());
///===========================================================
QFile file(src);
if ( file.open(QIODevice::WriteOnly) )
{
//clear the content
// file.resize(0);
file.seek(0);
file.write(QByteArray::number(IO.toInt()),1);
}
if(GetValue(port)==IO.toInt())
{
return true;
}
else
return false;
}
the relay is not changed, but when I run the executable sample the relay is turn on and off:
int main(int argc, char ** argv)
{
int pin = GPIO_PIN(7);
int i, value, board;
int ret = -1;
if ((board = boardInit()) < 0) {
printf("Fail to init board\n");
return -1;
}
if (board == BOARD_NANOPI_T2)
pin = GPIO_PIN(15);
if (argc == 2)
pin = GPIO_PIN(atoi(argv[1]));
if ((ret = exportGPIOPin(pin)) == -1) {
printf("exportGPIOPin(%d) failed\n", pin);
}
if ((ret = setGPIODirection(pin, GPIO_OUT)) == -1) {
printf("setGPIODirection(%d) failed\n", pin);
}
for (i = 0; i < STATUS_CHANGE_TIMES; i++) {
if (i % 2) {
value = GPIO_HIGH;
} else {
value = GPIO_LOW;
}
if ((ret = setGPIOValue(pin, value)) > 0) {
printf("%d: GPIO_PIN(%d) value is %d\n", i+1, pin, value);
} else {
printf("setGPIOValue(%d) failed\n", pin);
}
sleep(1);
}
unexportGPIOPin(pin);
return 0;
}
in that code also the value in that address changed like my code (change value file to 1 and 0 ) and the relay is working. where is the diffrence between my code and that code? both of them change the value content.
where is my code problem?