Monday, July 19, 2021

Connection refused: Why is my UNIX socket client giving me this?

Language:  C++

Environment: Ubuntu 20

Application:  Creating a UNIX Socket server


If you go out onto the Internet looking for help with this, you'll find oodles and oodles of articles, forum posts, blog posts, tutorials and everything in between explaining how TCP sockets work and how to create them, use them, debug them, take them out to the park and run around with them...

...but UNIX sockets get very little love, and that's not so good when you run into a problem with one.

(The easiest way to tell the difference is to look at the code presented by one of these sites.  Look at the socket() system call.  If the first parameter is AF_INET, you're working with an Internet socket.  If it says PF_UNIX, you're where you want to be.)

A UNIX socket is essentially a special file.  That's it.  That means all the stuff that you could run into when working with files can also impact you when working with UNIX sockets.  The beauty of this is that if you have any experience working with files from your C++ program, then you already have the experience you need to debug problems with your UNIX sockets.

Suppose your "Connection refused" error comes right after a line that looks something like this:

connect(server_,(const struct sockaddr *)&server_addr,sizeof(server_addr))

Inside sockaddr (which is a struct of type sockaddr_un) is a field that holds the path name.  Yes, that means file path.  So what might cause a connection refused?  Well, what sorts of things cause a failure when you try to open a file?  Maybe the file doesn't exist.  Maybe the process doesn't have access privileges on that file.  (See where I'm going with this?)

When the connect() function tries to open that UNIX socket, the socket needs to:

  • Exist.  Don't try to manually create it yourself using mkdir or touch.  That socket gets created when you run a UNIX socket server.  
  • Be a socket.  This is why you don't create it yourself.  When the socket server creates the socket and calls the bind() system call, the socket can now be connected to by a socket client.  Yes, that implies that you have to start your socket server before your client.
  • Be accessible.  Whatever user your process is running as needs to have permissions on that socket in whatever file directory it exists in.  
This is what a socket looks like on the file system when you do ls -l:

srwxrwxr-x  1 arcticfox arcticfox    0 Jul 19 21:13 my_sock

This one is in the /tmp directory, which is a nice, safe, out of the way place.  Notice the first letter for the file type is 's' as opposed to 'd' which it would be if it were a directory.  That's how we know it's a UNIX socket.   

So if you've done everything correctly but your client is refusing to connect, check these three things.


 So it's been a while since I've posted anything here.  It isn't that I died or stopped developing software.  It's that I'm in a radically different field of development and have prettymuch left web development behind for the time being.  

Now I'm working in Artificial Intelligence and robotics.  That is exactly as cool, and as terrifying, as it sounds.

I haven't posted lately because much of what I've been doing over the last few years has either had very little relevance to development in general or it was proprietary stuff that I couldn't share publicly even if there was some use in doing so.  

In my current position though, I get to work with lots of open source and/or non proprietary software as well, and I'll try to share what I learn as I learn it, as before.

Monday, December 18, 2017

Problems with Primefaces Picklists

Primefaces is awesome. JSF is awesome.

Know what isn't awesome? The documentation.

Don't get me wrong... The Primefaces document and the Showcase demo site are very good for introducing the components and the basics on how to use them. The problem is that sometimes they're a little too basic. For example, the picklist component. It says right in the Primefaces PDF that most often, pojos will be used with the picklist, and that it is necessary to implement a Converter to handle it... and that's it. It goes on to show how some facets can be used to make the component look more spiffy, but the developer is left with very little information on what the Converter is for, exactly and how to implement it.

That's why this post exists.

So here's an example that will hopefully help.

<p:picklist converter="#{shipConverter}" itemlabel="#{ship.name}" value="#{backingBean.pickDLM}" var="ship"/>

So here, the converter is just the name we give to our instance of the ShipConverter class, which implements Converter.  itemLabel is the field within one of the contained objects that will be displayed in the picklist windows.  Value is the DualListModel which is defined in the backing bean and serves as the source of data for the picklist.  Var is the reference to each individual item, the same as in a table or tree.

So how does that DualListModel work?

In your backing bean, you'll need your data source for the picklist. 

DualListModel<Ship> pickDLM = null;  //matches the value field on the view
List<Ship> shipSource = DatabaseSourceObject.getShips();
List<Ship> shipTarget = newArrayList<Ship>();

Notice that the source object is a list of Ship objects which will populate the left pane of the picklist.  The target is the right pane, and is initially empty.  If your project needed to pre-populate a few items in the right pane, you would add them to the target object here.  So now we put it all together:

pickDLM = new DualListModel<Ship(shipSource, shipTarget);

So then all you need in your backing bean is the getters and setters for the DualListModel. 

Now for the Converter...

@FacesConverter(value="shipConverter")
@Managedbean(name="shipConverter")
public class ShipConverter implements Converter{

  public ShipConverter(){}//Constructor Stub
  
  //This method provides an implementation for converting the strings in the pickList view back into the objects they represent.
  @Override
  public Object getAsObject(FacesContext context, UIComponent uiComponent, String value){
  pickList pickList = (PickList)uiComponent;
  DualListModel listModel = (DualListModel)pickList.getValue();
  for(Object item : listModel.getSource()){
    Ship ship = (Ship)item;
    if(ship.getName().equals(value)){
      return ship;
    }
  }
}

  //This method provides an implementation for getting the String value of an object in the picklist.
@Override
public String getAsString(FacesContext context, UIComponent uiComponent, Object object){
  String result = ((Ship)object).getName();
  return result;
}
}

That's it.  The idea is to specify exactly how to switch back and forth between the collection objects and their String representations in the picklist.

Enjoy!


Tuesday, April 11, 2017

CentOS 7 Networking in VirtualBox

I see a lot of results when Google searching on this problem and there is a wide variety of solutions, so this one may or may not work for you. It's a hybrid of a couple others I saw, and was arrived at through trial and error.

The environment:

Windows 7 (Host OS, and no I don't have Admin rights) CentOS 7 (Guest, I have root privileges) Oracle VM VirtualBox 4.3

Installing CentOS 7 into VirtualBox requires that you explicitly tell the VM that the ethernet cable is plugged in. That's no big deal in and of itself, but there's some configuration to be done.

Open the file /etc/sysconfig/network/scripts/ifcfg-enp0s3

Note that the filename is based on the name of your ethernet connection. If you don't know what that is, run an ifconfig command to find out.

Modify the following two lines in the file:

BOOTPROTO=shared change to BOOTPROTO=dhcp

ONBOOT=no change to ONBOOT=yes

Reboot your CentOS and verify. That's the approach that worked for me.

Monday, March 6, 2017

Liferay 7 Portlet pom.xml Issues in Eclipse

So I'm learning my way around Liferay 7 and one of my first efforts was to create a sample portlet for it.  The issue I was experiencing was that two of the dependencies were not able to resolve:

        <dependency>
            <groupid>com.liferay.portal</groupid>
            <artifactid>portal-service</artifactid>
            <version>${liferay.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupid>com.liferay.portal</groupid>
            <artifactid>util-java</artifactid>
            <version>${liferay.version}</version>
            <scope>provided</scope>
        </dependency>

The problem is that these dependencies, being auto generated by the Eclipse Liferay plugin, are using the older Liferay 6 naming conventions.  The newer naming conventions look like this:

        <dependency>
            <groupid>com.liferay.portal</groupid>
            <artifactid>com.liferay.portal.kernel</artifactid>
            <version>2.22.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupid>com.liferay.portal</groupid>
            <artifactid>com.liferay.util.java</artifactid>
            <version>2.2.2</version>
            <scope>provided</scope>
        </dependency>

Note, the artifactId now has a '.' delimited format instead of '-,'  and the version isn't the same as the Liferay version.  A complete list of the new names appears here.

Wednesday, December 14, 2016

Liferay 7 Portlet Deployment FrameworkEvent ERROR

So I'm learning Liferay 7 and at one point I slammed into this error when deploying a new portlet:

[Framework Event Dispatcher: Equinox Container: 80bc0073-27c2-0016-1b3f-f18a52a8a071][com_liferay_portal_osgi_web_servlet_context_helper:97] FrameworkEvent ERROR
org.osgi.framework.ServiceException: Exception in com.liferay.portal.osgi.web.servlet.context.helper.internal.ServletContextHelperRegistrationServiceFactory.getService()

Multiple attempts to search the web for some insights failed, so here we are, a new post at last!

The issue is actually fairly simple.  In my pom.xml file I had, among others, the following dependency:

   
   
<dependency>
     
<groupId>com.liferay.portal</groupId>
     
<artifactId>com.liferay.portal.kernel</artifactId>
     
<version>2.17.0</version>
   
</dependency>

This was actually colliding with the .jar already loaded into Tomcat.  The fix was simple:

   
    <dependency>
     
<groupId>com.liferay.portal</groupId>
     
<artifactId>com.liferay.portal.kernel</artifactId>
     
<scope>provided</scope>
     
<version>2.17.0</version>
   
</dependency>

By marking the dependency entry as 'provided' the jar won't be bundles into the .war file upon deployment.

So it would be good to go through and determine whether the version of this .jar in the dependency is different from the one in the portal instance.  (I presume it is.)  Either way it should have been listed as 'provided' in the first place.

Monday, September 7, 2015

Postbox: Now Worse than Microsoft

Normally I use this blog exclusively for technical articles but in this case I will be mixing a little tech with a little op-ed.

A while back I switched my E-mail client to Postbox, which is derived from Mozilla Thunderbird.  It wasn't free, but I didn't mind paying for something with a little more polish and presumably, support.  I had been happy with it for the time I used it, until recently when it automatically updated to version 4.  Cool.  It had a more mobile app aesthetic as is common for a lot of applications these days, and supposedly had a bunch of improvements and features.

What I didn't know at the time was that you have to pay for this upgrade.  No, having an existing license for the previous version does NOT unlock the new one.  I found that mildly annoying, since I use several paid-for applications that allow me to continue to use my license to receive upgrades.

So whatever... I was happy with Postbox 3 so I didn't worry too much about it, hoping that when the "trial period" ended I could just downgrade back to the version I had already paid for.  Kinda like how if, in the past, if you didn't want to pay to buy the newest Windows version you could just stick with the one you already had.  (You still can, if you don't like being spied on.  I am still sitting on Windows 7 thank you very much.)

Guess what?  That isn't an option.  As of this morning, I can no longer use Postbox to send or receive E-mails unless I pay for the upgraded license.  If I had kept my original installation .exe I could perhaps have reinstalled the old one with the license, but I generally don't keep that stuff on my system to clutter it up because USUALLY if I need to roll back I can always go online and get the older version downloaded again.

So here I sit, unable to use software I paid for.  Looks like I'll be importing my E-mails into one of the free E-mail clients, like Thunderbird.

Before I get to that though, I have some remarks for the people at Postbox.  I notice their "Contact Us" page doesn't seem to have a simple mechanism for sending them some feedback, though they do provide a snail mail address for "Fan Mail."

A bit full of ourselves, are we?

I do find it telling that they don't seem to want to hear directly from their "fans" through some kind of E-mail mechanism.  Anyway, here's what I have to say.

Dear Postbox Management and Development team,

I really have to hand it to you.  You have managed to make Microsoft, the company with one of the most evil reputations in the IT industry, look reasonable.  I can understand how a small company that doesn't have a ton of operating capital might need to charge for major updates to their product.  I get that, but what you've done here is to eliminate choice.  As a user of your product, I'm being forced to pay you to continue to use software that I already paid for once before.  As far as I can tell, I've never had the option to downgrade back from the trial version of Postbox 4, and if you included some kind of warning before I installed the version 4 update, I didn't notice it.  I've read articles in the past about the reputation your company has with its customers, and what I'm seeing here does seem to support the idea that you really don't have much regard for your customers, only their money.  On top of that, you have the gall to call incoming correspondence "fan mail."  I don't know whether to laugh out loud or just shake my head ruefully.  For you, I think I'll try to do both simultaneously.  

It isn't even like your product is great enough to justify paying for every major upgrade (or buying the "lifetime license" I've heard about.)  As someone who has used both your product and Mozilla Thunderbird, I don't see a dime's worth of difference between the two, only Mozilla gives Thunderbird away for free.  You know Thunderbird, I assume, as it's the basis for Postbox in the first place.  If I recall correctly, I purchased Postbox originally for $10, and now you want another $15 for the privilege of continuing to use the application.  Your site talks about all of the wonderful new features of Postbox 4, but I never noticed much of a difference except for a rather more awkward and Romper-Room looking interface.

In any case, I won't be paying you again for the same software, whatever your claims are about the superiority of version 4.  You got me once, it won't happen again.  Frankly I never saw much advantage to Postbox over Thunderbird in the first place, and had only been using it because I'd already paid for it.  I will close this message now, but I won't wish you well.  I think companies that do business like yours does deserve to fail.  Instead, I'll wish you wisdom, that you might realize how this alienates customers and will make good adjustments in the future.  

Ok, with that out of the way, let's talk about migrating to Thunderbird.

First, don't bother with the instructions on Postbox's support page.  As of the time I'm writing this, they're from 2009 and not only use basically the same procedure as if you were using Thunderbird already (remember, Postbox is Thunderbird with tweaks.) but they also even provide a link to a Mozilla support page for additional information.

It's really just a simple mater of using Import and Export tools from within Thunderbird to import your E-mail folders from Postbox.  You'll find them in Windows in AppData/Roaming/Postbox and AppData/Local/Postbox.  I haven't quite got the hang of managing E-mail folders so I can't offer any advice there, but at least this will enable you to save your messages so you can safely get rid of Postbox if you want to.