inline void enable_break_away(::boost::winapi::HANDLE_ h, std::error_code & ec)
{
    workaround::JOBOBJECT_EXTENDED_LIMIT_INFORMATION_ info;


    if (!workaround::query_information_job_object(
                    h,
                    workaround::JobObjectExtendedLimitInformation_,
                    static_cast<void*>(&info),
                    sizeof(info),
                    nullptr))
    {
        ec = get_last_error();
        return;
    }

    if ((info.BasicLimitInformation.LimitFlags & workaround::JOB_OBJECT_LIMIT_BREAKAWAY_OK_) != 0)
        return;

    info.BasicLimitInformation.LimitFlags |= workaround::JOB_OBJECT_LIMIT_BREAKAWAY_OK_;

    if (!workaround::set_information_job_object(
                h,
                workaround::JobObjectExtendedLimitInformation_,
                static_cast<void*>(&info),
                sizeof(info)))
    {
        ec = get_last_error();
        return;
    }
}
int set_module_option(wchar_t* option_name, wchar_t const* option_value)
{
	char tmp_option_value[MAX_STRING_SIZE * 2] = {0};
	int error_code =0x0;
	size_t size = 0x0;
	errno_t errno;

	error_code = load_config_file(__config_file_path);
	if(error_code == APP_FAULT){	__last_error_code = get_last_error();	goto GOTO;}

	error_code = check_segd_option(option_name);
	if(error_code == APP_FAULT){	__last_error_code = get_last_error();	goto GOTO;}

	errno = wcstombs_s(&size, tmp_option_value, sizeof(tmp_option_value), option_value, sizeof(tmp_option_value));
	if(errno != 0){	__last_error_code = IDS_STRING5015; 	goto GOTO;}

	tmp_option_value[size] = 0x0;
	error_code = modify_segd_option(option_name, tmp_option_value);
	if(error_code == APP_FAULT){	__last_error_code = get_last_error();	goto GOTO;}

	error_code = save_config_file(__config_file_path);
	if(error_code == APP_FAULT){	__last_error_code = get_last_error();}

GOTO:
	return error_code;
}
int save_config_file(char_t const* config_path)
{
	int i = 0;
	int size = 0;
	HANDLE file_handle = NULL;
	char tmp_buf[MAX_STRING_SIZE] = {0};

	file_handle	= CreateFile(config_path, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 
		NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

	if(file_handle == INVALID_HANDLE_VALUE){

		set_last_error(IDS_STRING5008);
		output_log(IDS_STRING5008, get_last_error());
		return APP_FAULT;
	}

	for(i = 0; i < __config_file_line_size; ++i){
		strcpy(tmp_buf, __config_file_lines[i].line_);
		size = strlen(tmp_buf);
		tmp_buf[size++] = 0xd;
		tmp_buf[size++] = 0xa;
		tmp_buf[size] = NULL;
		if(!WriteFile(file_handle, tmp_buf, size, (DWORD*)&size, NULL)){
			set_last_error(IDS_STRING5011);
			output_log(IDS_STRING5011, get_last_error());
		}
	}

	if(file_handle != INVALID_HANDLE_VALUE) CloseHandle(file_handle);
	return APP_SUCCESS;
}
Exemple #4
0
void *
dlopen(const char* path, int mode __UNUSED__)
{
   HMODULE module = NULL;

   if (!path)
     {
        module = GetModuleHandle(NULL);
        if (!module)
          get_last_error("GetModuleHandle returned: ");
     }
   else
     {
        char        *new_path;
        size_t       l;
        unsigned int i;

        /* according to MSDN, we must change the slash to backslash */
        l = strlen(path);
        new_path = (char *)malloc(sizeof(char) * (l + 1));
        if (!new_path)
          {
             if (dl_err)
               free(dl_err);
             dl_err = strdup("not enough resource");
             dl_err_viewed = 0;
             return NULL;
          }
        for (i = 0; i <= l; i++)
          {
             if (path[i] == '/')
               new_path[i] = '\\';
             else
               new_path[i] = path[i];
          }
#ifdef UNICODE
        {
           wchar_t *wpath;

           wpath = evil_char_to_wchar(new_path);
           module = LoadLibrary(wpath);
           free(wpath);
        }
#else
        module = LoadLibraryEx(new_path, NULL,
                               LOAD_WITH_ALTERED_SEARCH_PATH);
#endif /* ! UNICODE */
        if (!module)
          get_last_error("LoadLibraryEx returned: ");

        free(new_path);
     }

   return module;
}
Exemple #5
0
inline bool wait_impl(const group_handle & p, std::error_code & ec, std::chrono::system_clock::rep wait_time)
{
    ::boost::winapi::DWORD_ completion_code;
    ::boost::winapi::ULONG_PTR_ completion_key;
    ::boost::winapi::LPOVERLAPPED_ overlapped;

    auto start_time = std::chrono::system_clock::now();

    while (workaround::get_queued_completion_status(
                                       p._io_port, &completion_code,
                                       &completion_key, &overlapped, wait_time))
    {
        if (reinterpret_cast<::boost::winapi::HANDLE_>(completion_key) == p._job_object &&
             completion_code == workaround::JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO_)
        {

            //double check, could be a different handle from a child
            workaround::JOBOBJECT_BASIC_ACCOUNTING_INFORMATION_ info;
            if (!workaround::query_information_job_object(
                    p._job_object,
                    workaround::JobObjectBasicAccountingInformation_,
                    static_cast<void *>(&info),
                    sizeof(info), nullptr))
            {
                ec = get_last_error();
                return false;
            }
            else if (info.ActiveProcesses == 0)
                return false; //correct, nothing left.
        }
        //reduce the remaining wait time -> in case interrupted by something else
        if (wait_time != ::boost::winapi::infinite)
        {
            auto now = std::chrono::system_clock::now();
            auto diff = std::chrono::duration_cast<std::chrono::milliseconds>(now - start_time);
            wait_time -= diff.count();
            start_time = now;
            if (wait_time <= 0)
                return true; //timeout with other source
        }

    }

    auto ec_ = get_last_error();
    if (ec_.value() == ::boost::winapi::wait_timeout)
        return true; //timeout

    ec = ec_;
    return false;
}
Exemple #6
0
bool qjdns_sock_setMulticast6(int s, unsigned char *addr, int *errorCode)
{
#ifdef HAVE_IPV6
	int ret;
	struct ipv6_mreq mc;

	memset(&mc, 0, sizeof(mc));
	memcpy(mc.ipv6mr_multiaddr.s6_addr, addr, 16);
	mc.ipv6mr_interface = 0;

	ret = setsockopt(s, IPPROTO_IPV6, IPV6_JOIN_GROUP, (const char *)&mc, sizeof(mc));
	if(ret != 0)
	{
		if(errorCode)
			*errorCode = get_last_error();
		return false;
	}
	return true;
#else
	Q_UNUSED(s);
	Q_UNUSED(addr);
	Q_UNUSED(errorCode);
	return false;
#endif
}
Exemple #7
0
	s32 bind(s32 s, vm::cptr<sockaddr> addr, u32 addrlen)
	{
		libnet.warning("bind(s=%d, family=*0x%x, addrlen=%d)", s, addr, addrlen);
		std::shared_ptr<sys_net_socket> sock = idm::get<sys_net_socket>(s);

		if (!sock)
		{
			libnet.error("bind(): socket does not exist");
			return -1;
		}

		::sockaddr_in saddr;
		memcpy(&saddr, addr.get_ptr(), sizeof(::sockaddr_in));
		saddr.sin_family = addr->sa_family;
		const char *ipaddr = ::inet_ntoa(saddr.sin_addr);
		libnet.warning("binding to %s on port %d", ipaddr, ntohs(saddr.sin_port));
		s32 ret = ::bind(sock->s, (const ::sockaddr*)&saddr, addrlen);

		if (ret != 0)
		{
			libnet.error("bind(): error %d", get_errno() = get_last_error());
			return -1;
		}

		return ret;
	}
Exemple #8
0
	s32 recvfrom(s32 s, vm::ptr<char> buf, u32 len, s32 flags, vm::ptr<sockaddr> addr, vm::ptr<u32> paddrlen)
	{
		libnet.warning("recvfrom(s=%d, buf=*0x%x, len=%d, flags=0x%x, addr=*0x%x, paddrlen=*0x%x)", s, buf, len, flags, addr, paddrlen);
		std::shared_ptr<sys_net_socket> sock = idm::get<sys_net_socket>(s);

		::sockaddr _addr;
		::socklen_t _paddrlen;

		memcpy(&_addr, addr.get_ptr(), sizeof(::sockaddr));
		_addr.sa_family = addr->sa_family;

		if (!sock || !buf || len == 0)
		{
			libnet.error("recvfrom(): invalid arguments buf= *0x%x, len=%d", buf, len);
			return SYS_NET_EINVAL;
		}

		if (s < 0) {
			libnet.error("recvfrom(): invalid socket %d", s);
			return SYS_NET_EBADF;
		}

		s32 ret = ::recvfrom(sock->s, buf.get_ptr(), len, flags, &_addr, &_paddrlen);
		*paddrlen = _paddrlen;

		if (ret < 0)
		{
			libnet.error("recvfrom(): error %d", get_errno() = get_last_error());
			return -1;
		}

		return ret;
	}
 bool in_group(std::error_code &ec) const noexcept
 {
     ::boost::detail::winapi::BOOL_ value;
     if (!::boost::detail::winapi::IsProcessInJob(proc_info.hProcess, nullptr, &value))
         ec = get_last_error();
     return value!=0;
 }
Exemple #10
0
	s32 socketclose(s32 s)
	{
		libnet.warning("socketclose(s=%d)", s);
		std::shared_ptr<sys_net_socket> sock = idm::get<sys_net_socket>(s);

		if (!sock)
		{
			libnet.error("socketclose(): socket does not exist, or was already closed");
			return -1;
		}

#ifdef _WIN32
		s32 ret = ::closesocket(sock->s);
#else
		s32 ret = ::close(sock->s);
#endif

		if (ret != 0)
		{
			libnet.error("socketclose(): error %d", get_errno() = get_last_error());
			return -1;
		}

		idm::get<sys_net_socket>(s)->s = -1;
		idm::remove<sys_net_socket>(s);

		return ret;
	}
Exemple #11
0
	/*** CharsetConvert ***/
	Bytes* CharsetConvert::Convert(const char* src, const char* from_code, const char* to_code){
		// open
		iconv_t ic =iconv_open(to_code, from_code);
		if((iconv_t)-1 == ic){
			ERROR("fail to %s, %s", __FUNCTION__, get_last_error_desc());
			return 0;
		}

		// conv
		Bytes* bs =SafeNew<Bytes>();
		char buf[64] ={0};
		size_t os =64;
		char* ob =0;
		size_t is =strlen(src);
		char* ib =const_cast< char* >(src);

		while(is > 0){
			os =64;
			ob =buf;
			const int err =iconv(ic, &ib, &is, &ob, &os);
			if(err == -1){
				if(get_last_error() != E2BIG){
					ERROR("fail to %s, %s", __FUNCTION__, get_last_error_desc());
					iconv_close(ic);
					return 0;
				}
			}
			bs->write(buf, ob-buf);
		}

		// close
		iconv_close(ic);
		return bs;
	}
Exemple #12
0
 bool has(handle_t proc, std::error_code & ec) noexcept
 {
     ::boost::winapi::BOOL_ is;
     if (!::boost::winapi::IsProcessInJob(proc, _job_object,  &is))
         ec = get_last_error();
     return is!=0;
 }
Exemple #13
0
	s32 socket(s32 family, s32 type, s32 protocol)
	{
		libnet.warning("socket(family=%d, type=%d, protocol=%d)", family, type, protocol);

		if (type < 1 || type > 10 || (type > 4 && type < 6) || (type > 6 && type < 10))
		{
			get_errno() = SYS_NET_EPROTONOSUPPORT;
			return -1;
		}

		// HACKS: Neither Unix nor Windows support TCP/UDP over UDPP2P.
		// But what's the usage of it anyways?
		if (type == SOCK_STREAM_P2P)
		{
			libnet.warning("SOCK_STREAM_P2P is not properly implemented.");
			type = SOCK_STREAM;
		}
		else if (type == SOCK_DGRAM_P2P)
		{
			libnet.warning("SOCK_DGRAM_P2P is not properly implemented.");
			type = SOCK_DGRAM;
		}

		socket_t sock = ::socket(family, type, protocol);

		if (sock < 0)
		{
			libnet.error("socket(): error %d", get_errno() = get_last_error());
			return -1;
		}

		return idm::make<sys_net_socket>(sock);
	}
Exemple #14
0
	s32 connect(s32 s, vm::ptr<sockaddr> addr, u32 addrlen)
	{
		libnet.warning("connect(s=%d, family=*0x%x, addrlen=%d)", s, addr, addrlen);
		std::shared_ptr<sys_net_socket> sock = idm::get<sys_net_socket>(s);

		if (!sock)
		{
			libnet.error("connect(): socket does not exist");
			return -1;
		}

		::sockaddr_in saddr;
		memcpy(&saddr, addr.get_ptr(), sizeof(::sockaddr_in));
		saddr.sin_family = addr->sa_family;

		libnet.warning("connecting to %s on port %d", ::inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port));
		s32 ret = ::connect(sock->s, (const ::sockaddr*)&saddr, addrlen);
		
		if (ret != 0)
		{
			if ((get_errno() = get_last_error()) != SYS_NET_EWOULDBLOCK)
			{
				libnet.error("connect(): error %d", get_errno().get_ref());
			}
			
			return -1;
		}

		return ret;
	}
Exemple #15
0
void rxtx_print_error(struct rxtx_data *rxtx,
                      const char *prefix, const char *suffix)
{
    enum error_type type;
    int val;

    get_last_error(&rxtx->last_error, &type, &val);

    if (val != 0) {
        switch (type) {
            case ETYPE_ERRNO:
                printf("%s%s%s", prefix, strerror(val), suffix);
                break;

            case ETYPE_CLI:
                printf("%s%s%s", prefix, cmd_strerror(val, 0), suffix);
                break;

            case ETYPE_BLADERF:
                printf("%s%s%s", prefix, bladerf_strerror(val), suffix);
                break;

            default:
                printf("%sBUG: Unexpected status=%d%s", prefix, val, suffix);
        }
    } else {
        printf("%sNone%s", prefix, suffix);
    }
}
Exemple #16
0
int TCPSockStream::send_n(const unsigned char *buf,size_t len,long timeout)
{
	int ret;
	ssize_t r;
	size_t s;
	ret = handle_write_ready(timeout);
	if(ret>0) // timeout
		return 1;
	if(ret<0)
		return -1;
	s = 0;
	do 
	{
#ifdef WIN32
		r = send(sock_,(const char*)buf+s,len,0);
#else
		r = send(sock_,(const void*)(buf+s),len,0);
#endif
		if(r < 0) // send error
		{
			errno_ = get_last_error();
			return -1;
		}
		s += r;
		len-=r;
	} while(len>0);

	return 0;
}
Exemple #17
0
/** fd **/
void close_fd(int fd) {
    while(::close(fd) != 0) {
        if(get_last_error() != EINTR) {
            break;
        }
    }
}
FCGICache::~FCGICache()
{
	if( _buf )
	{
		delete []_buf;
	}

	if( _file )
	{
		_file->close();
		/*
		* 临时文件 close() 后自动删除
		if(!WINFile::remove(AtoT(_fileName).c_str()))
		{
			TRACE("WINFile::remove() %s failed,%s.\r\n", _fileName.c_str(), get_last_error().c_str());
		}
		*/

		delete _file;
	}
	else
	{
		/*
		* 由于每获得一个临时文件名,系统就将创建一个空文件.
		* 没有使用 _file 只需把这个空文件删除即可.
		*/
		if(!WINFile::remove(AtoT(_fileName).c_str()))
		{
			TRACE("WINFile::remove() %s failed,%s.\r\n", _fileName.c_str(), get_last_error().c_str());
		}
	}
}
Exemple #19
0
int database::init(OBJECT *parent)
{
	gld_string flags = get_clientflags_property().get_string();
	
	gl_verbose("mysql_connect(hostname='%s',username='******',password='******',schema='%s',port=%u,socketname='%s',clientflags=0x%016llx[%s])",
		(const char*)hostname,(const char*)username,(const char*)password,(const char*)schema,port,(const char*)socketname,get_clientflags(),(const char*)flags);

	mysql = mysql_real_connect(mysql_client,hostname,username,strcpy(password,"")?password:NULL,NULL,port,socketname,(unsigned long)clientflags);
	if ( mysql==NULL )
		exception("mysql connect failed - %s", mysql_error(mysql_client));
	else
		gl_verbose("MySQL server info: %s", mysql_get_server_info(mysql));

	// autoname schema
	if ( strcmp(get_schema(),"")==0 )
	{
		char buffer[1024];
		gld_global model("modelname");
		if ( model.to_string(buffer,sizeof(buffer))>0 )
			set_schema(buffer);
	}

	// drop schema
	if ( get_options()&DBO_DROPSCHEMA && query("DROP DATABASE IF EXISTS `%s`", get_schema()) )
	{
		if ( strcmp(get_schema(),"gridlabd")==0 )
			gl_warning("%s uses NEWDB option on the default schema '%s' - this is extremely risky", get_name(), get_schema());
		gl_verbose("schema '%s' dropped ok", get_schema());
	}

	// check schema
	MYSQL_RES *res = mysql_list_dbs(mysql,get_schema());
	if ( mysql_num_rows(res)==0 )
	{
		if ( !(get_options()&DBO_NOCREATE) )
		{
			if ( query("CREATE DATABASE IF NOT EXISTS `%s`", get_schema()) )
				gl_verbose("created schema '%s' ok", get_schema());
		}
		else
			exception("NOCREATE option prevents automatic creation of schema '%s'", get_schema());
	}
	else
		gl_verbose("schema '%s' found ok", get_schema());

	// use schema
	if ( mysql_select_db(mysql,get_schema())!=0 )
		exception("unable to select schema '%s'", get_schema());

	// execute on_init script
	if ( strcmp(get_on_init(),"")!=0 )
	{
		gl_verbose("%s running on_init script '%s'", get_name(), get_on_init());
		int res = run_script(get_on_init());
		if ( res<=0 )
			exception("on_init script '%s' failed at line %d: %s", get_on_init(), -res, get_last_error());
	}
	return 1;
}
Exemple #20
0
static void do_test_libeprom24x(void)
{  
  int value;

  do {
    print_menu();
    
    printf("Enter choice : ");
    scanf("%d",&value);
    
    switch(value) {
    case 1:
      get_prod_info();
      break;
    case 2:
      get_last_error();
      break;
    case 3:
      initialize();
      break;
    case 4:
      finalize();
      break;
    case 5:
      read_u8();
      break;
    case 6:
      read_u16();
      break;
    case 7:
      read_u32();
      break;
    case 8:
      read_to_buffer();
      break;
    case 9:
      write_u8();
      break;
    case 10:
      write_u16();
      break;
    case 11:
      write_u32();
      break;
    case 12:
      write_from_buffer();
      break;
    case 13:
      erase_chip();
      break;
    case 100: /* Exit */
      break;
    default:
      printf("Illegal choice!\n");
    }
  } while (value != 100);

  return;
}
    SILICIUM_USE_RESULT
    inline boost::system::error_code set_environment_variable(os_c_string key,
                                                              os_c_string value)
    {
#ifdef _WIN32
        if (!SetEnvironmentVariableW(key.c_str(), value.c_str()))
        {
            return get_last_error();
        }
#else
        if (setenv(key.c_str(), value.c_str(), 1) != 0)
        {
            return get_last_error();
        }
#endif
        return boost::system::error_code();
    }
Exemple #22
0
void joy_core::internal_finalize(JOY_DEV dev)
{
   // Finalize the I/O object
  m_joy_dev_info[dev].joy_io_auto->finalize();

  JOY_LIB_STATUS status; 
  get_last_error(&status);  
}
Exemple #23
0
	// Functions
	s32 accept(s32 s, vm::ptr<sockaddr> addr, vm::ptr<u32> paddrlen)
	{
		libnet.warning("accept(s=%d, family=*0x%x, paddrlen=*0x%x)", s, addr, paddrlen);
		std::shared_ptr<sys_net_socket> sock = idm::get<sys_net_socket>(s);

		if (!sock)
		{
			libnet.error("accept(): socket does not exist");
			return -1;
		}

		s32 ret;

		if (!addr)
		{
			ret = ::accept(sock->s, nullptr, nullptr);

			if (ret < 0)
			{
				libnet.error("accept(): error %d", get_errno() = get_last_error());
				return -1;
			}
		}
		else
		{
			::sockaddr _addr;
			::socklen_t _paddrlen = 16;

			ret = ::accept(sock->s, &_addr, &_paddrlen);

			if (ret < 0)
			{
				libnet.error("accept(): error %d", get_errno() = get_last_error());
				return -1;
			}

			*paddrlen = _paddrlen;
			addr->sa_len = _paddrlen;
			addr->sa_family = _addr.sa_family;
			memcpy(addr->sa_data, _addr.sa_data, addr->sa_len - 2);
		}

		return idm::make<sys_net_socket>(ret);
	}
Exemple #24
0
void ipc_write(IPC* ipc)
{
    if (ipc->cmd & HAL_REQ_FLAG)
    {
        ipc->cmd &= ~HAL_REQ_FLAG;
        switch (get_last_error())
        {
        case ERROR_OK:
            //no error
            break;
        case ERROR_SYNC:
            //asyncronous completion
            return;
        default:
            ipc->param3 = get_last_error();
        }
        svc_call(SVC_IPC_POST, (unsigned int)ipc, 0, 0);
    }
}
Exemple #25
0
void delete_fd_from_epoll(int epollfd, int fd) {
    if(0 != epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, 0)) {
        if(get_last_error() == ENOENT) {
            return;
        }
        else {
            ERROR("fail to call epoll_ctl EPOLL_CTL_DEL, %s", get_last_error_desc());
        }
    }
}
Exemple #26
0
int
dlclose(void* handle)
{
   if (FreeLibrary(handle))
     return 0;
   else
     {
        get_last_error("FreeLibrary returned: ");
        return -1;
     }
}
Exemple #27
0
bool resume_thread(HANDLE handle)
{
    if (-1 == ResumeThread(handle)){

        get_last_error(__func__, __LINE__);

        return false;
    }

    return true;
}
Exemple #28
0
ssize_t TCPSockStream::recv_n(unsigned char *buf,size_t maxlen,long timeout)
{
	int ret;
	ssize_t r;
	size_t s;
	s = 0;

	do 
	{
#ifdef WIN32
		r = recv(sock_,(char*)buf+s,maxlen,0);
#else
		r = recv(sock_,(void*)(buf+s),maxlen,0);
#endif
		if(r < 0||r == 0) // send error
		{
			//int nErrorCode   =   WSAGetLastError(); 

			if(r < 0)
			{

				ret = handle_read_ready(timeout);
				errno_ = get_last_error();
				if(ret>0) // timeout
					return -2;	

				if(ret < 0) // ´íÎó
				{
#ifdef WIN32
					if(errno_ != WSAEWOULDBLOCK)
#else
					//if(errno_ != WSAEWOULDBLOCK)
#endif
					{
						return -1;
					}
				}
			}
			else if(r ==0)
			{
				return -1;
			}
		}
		if(r > 0)
		{
			s += r;
			maxlen-=r;
		}
		
	} while(maxlen>0);
	return s;
}
Exemple #29
0
bool modify_fd_in_epoll(int epollfd, int fd, int events, void* context) {
    struct epoll_event evt;
    memset(&evt, 0, sizeof(evt));
    evt.events =events;
    evt.data.ptr =context;
    if(0 != epoll_ctl(epollfd, EPOLL_CTL_MOD, fd, &evt)) {
        if(get_last_error() != ENOENT) {
            ERROR("fail to call epoll_ctl EPOLL_CTL_ADD, %s", get_last_error_desc());
        }
        return false;
    }
    return true;
}
Exemple #30
0
static void loras_timer_poll_timeout(LORA* lora)
{
    int last_error;
#if (LORA_DEBUG)
    uint32_t duration_ms;
    ++lora->polls_cnt;
#endif

    if (lora->status != LORA_STATUS_TRANSFER_IN_PROGRESS)
    {
        loras_fatal(lora);
#if (LORA_DEBUG)
        printf("[loras] [fatal error] unexpected status %d => server closed\n", lora->status);
#endif
        return;
    }

    (lora->tx ? loras_hw_tx_async_wait : loras_hw_rx_async_wait)(lora);

    last_error = get_last_error();

#if (LORA_DEBUG)
    //check for internal unexpected errors (ex. ERROR_INVALID_STATE -- chip is in invalid state)
    if (!(last_error >= ERROR_OK || last_error == ERROR_TIMEOUT))
    {
        loras_fatal(lora);
        printf("[loras] [fatal error] unexpected error %d => server closed\n", last_error);
        return;
    }
#endif

    switch (lora->status)
    {
    case LORA_STATUS_TRANSFER_IN_PROGRESS:
        timer_start_ms(lora->timer_poll_timeout, LORA_POLL_TIMEOUT_MS);
        //note: do not check if last_error == ERROR_OK (should be)
        ipc_post_inline(lora->process, HAL_CMD(HAL_LORA, LORA_TRANSFER_IN_PROGRESS), 0, 0, last_error);
        break;
    case LORA_STATUS_TRANSFER_COMPLETED:
        timer_stop(lora->timer_txrx_timeout, 0, HAL_LORA);
#if (LORA_DEBUG)
        duration_ms = loras_get_uptime_ms() - lora->transfer_in_progress_ms;
        printf("[loras] [info] poll completed duration_ms:%u polls_cnt:%u\n", duration_ms, lora->polls_cnt);
#endif
        ipc_post_inline(lora->process, HAL_CMD(HAL_LORA, LORA_TRANSFER_COMPLETED), 0, 0, last_error);
        break;
    default:
        error(ERROR_NOT_SUPPORTED);
        break;
    }
}